Hướng dẫn python __init__ is not called - python __init__ không được gọi

Hãy để tôi bắt đầu với điều này không phải là sự lặp lại tại sao __init__ không được gọi nếu __new__ được gọi không có args. Tôi đã cố gắng xây dựng cẩn thận một số mã mẫu cho __new__ và __init__ không có lời giải thích nào tôi có thể tìm thấy.

Các tham số cơ bản:

  • Có một lớp cơ sở gọi là Notmine vì nó đến từ một thư viện khác (tôi sẽ tiết lộ ở cuối, không quan trọng ở đây)
  • Lớp đó có một phương thức __init__ lần lượt gọi phương thức _parse
  • Tôi cần ghi đè phương thức _parse trong các lớp con
  • lớp con nào tôi tạo ra không được biết đến cho đến khi gọi
  • Tôi biết có các phương pháp thiết kế nhà máy nhưng tôi không thể sử dụng chúng ở đây (nhiều hơn ở cuối)
  • Tôi đã cố gắng sử dụng cẩn thận super để tránh các vấn đề trong ghi nhật ký Python: Tại sao __init__ được gọi là hai lần?
  • Tôi biết đây cũng là "một cơ hội Tóm tắtBaseMhtod nhưng điều đó không giúp được gì

Dù sao, __init__ nên được gọi sau __new__ và đối với mọi giải thích về lý do tại sao một số mẫu dưới đây không hoạt động, tôi dường như có thể chỉ ra các trường hợp khác hoạt động và loại trừ lời giải thích.

class NotMine(object): def __init__(self, *args, **kwargs): print "NotMine __init__" self._parse() def _parse(self): print "NotMine _parse" class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) return obj elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) return obj else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) return obj class AA(ABC): def _parse(self): print "AA _parse" class BB(ABC): def __init__(self, *args, **kw): print "BB_init:*%s, **%s"%(args,kw) super(BB,self).__init__(self,*args,**kw) def _parse(self): print "BB _parse" class CCC(AA): def _parse(self): print "CCCC _parse" print("########### Starting with ABC always calls __init__ ############") ABC("AA") # case 1 ABC("BB") # case 2 ABC("NOT_AA_OR_BB") # case 3 print("########### These also all call __init__ ############") AA("AA") # case 4 BB("BB") # case 5 AA("NOT_AA_OR_BB") # case 6 BB("NOT_AA_OR_BB") # case 7 CCC("ANYTHING") # case 8 print("########### WHY DO THESE NOT CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11

Nếu bạn thực thi mã, bạn có thể thấy rằng mỗi cuộc gọi đến __new__, nó sẽ thông báo "cửa nào" nó đang xuất hiện và với loại nào. Tôi có thể thoát khỏi cùng một "cửa" với cùng một đối tượng "loại" và có __init__ được gọi trong một trường hợp chứ không phải cái kia. Tôi đã xem xét MRO của lớp "gọi" và không cung cấp cái nhìn sâu sắc vì tôi có thể gọi lớp đó (hoặc một subcass như trong CCC) và đã gọi __init__.

Ghi chú kết thúc: Thư viện class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 3 tôi đang sử dụng là Genshi Markuptemplate và lý do không sử dụng phương pháp thiết kế nhà máy là Templateloader của họ cần một lớp mặc định để xây dựng. Tôi không biết cho đến khi tôi bắt đầu phân tích cú pháp, điều mà tôi làm trong __new__. Có rất nhiều phép thuật Voodoo tuyệt vời mà Genshi Loaders và Mẫu làm điều đó làm cho điều này xứng đáng với nỗ lực. The class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 3 library I'm using is the Genshi MarkupTemplate and the reason for not using a Factory design method is that their TemplateLoader needs a defaultClass to construct. I don't know until I start parsing, which I do in __new__. There is a lot of cool voodoo magic that genshi loaders and templates do that make this worth the effort.

Tôi có thể chạy một thể hiện không sửa đổi của trình tải của họ và hiện tại mọi thứ đều hoạt động miễn là tôi chỉ vượt qua lớp ABC (Tóm tắt Sắp xếp-Vactory) làm mặc định. Mọi thứ đang hoạt động tốt nhưng hành vi không giải thích được này là một lỗi gần như chắc chắn sau đó.

Cập nhật: Ignacio, đóng đinh câu hỏi dòng trên cùng, nếu đối tượng được trả về không phải là "thể hiện" CLS thì __init__ không được gọi. Tôi thấy rằng gọi "hàm tạo" (ví dụ: class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 6 là sai vì nó sẽ gọi lại __new__ và bạn đã quay lại ngay khi bạn bắt đầu. Bạn có thể sửa đổi một con đường khác. Điều đó chỉ có nghĩa là bạn gọi class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 8 hai lần thay vì vô hạn . Một giải pháp làm việc là chỉnh sửa class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 9 ở trên như: Ignacio, nailed the top line question, if the returned object is not an "instance of" cls then __init__ is not called. I do find that calling the "constructor" (e.g. class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 6 is wrong as it will call __new__ again and you are right back where you started. You could modify an arg to take a different path. That just means you call class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 8 twice rather than infinitely. A working solution is to edit class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11 9 above as:

class ABC(NotMine): def __new__(cls,name,*args, **kwargs): print "-"*80 print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs) if name == 'AA': obj = super(NotMine,ABC).__new__(AA,*args,**kwargs) print "Exiting door number 1 with an instance of: %s"%type(obj) elif name == 'BB': obj = super(NotMine,ABC).__new__(BB,*args,**kwargs) print "Exiting door number 2 with an instance of: %s"%type(obj) elif name == 'CCC': obj = super(NotMine,ABC).__new__(CCC,*args,**kwargs) print "Exiting door number 3 with an instance of: %s"%type(obj) else: obj = super(NotMine,ABC).__new__(cls,*args,**kwargs) print "Exiting door number 4 with an instance of: %s"%type(obj) ## Addition to decide who calls __init__ ## if isinstance(obj,cls): print "this IS an instance of %s So call your own dam __init__"%cls return obj print "this is NOT an instance of %s So __new__ will call __init__ for you"%cls obj.__init__(name,*args, **kwargs) return obj print("########### now, these DO CALL __init__ ############") AA("BB") # case 9 BB("AA") # case 10 CCC("BB") # case 11

Lưu ý một vài dòng cuối cùng. Không gọi __init__ nếu đó là một lớp "khác" không có ý nghĩa với tôi, đặc biệt là khi lớp "khác nhau" vẫn là một lớp con của lớp gọi __init__. Tôi không thích chỉnh sửa ở trên nhưng ít nhất tôi có được các quy tắc tốt hơn một chút bây giờ.

Bạn có thể gọi __ init __ trong Python không?

Bạn không thể gọi chúng một cách rõ ràng.Chẳng hạn, khi bạn tạo một đối tượng mới, Python sẽ tự động gọi phương thức __new__, từ đó gọi phương thức __init__.Phương thức __str__ được gọi khi bạn in () một đối tượng.Mặt khác, các phương pháp do người dùng định nghĩa, như Stefi.. For instance, when you create a new object, Python automatically calls the __new__ method, which in turn calls the __init__ method. The __str__ method is called when you print() an object. On the other hand, user-defined methods, like stefi.

__ init __ được gọi là tự động?

Lưu ý: Hàm __init __ () được gọi tự động mỗi khi lớp được sử dụng để tạo một đối tượng mới.The __init__() function is called automatically every time the class is being used to create a new object.

Có cái gì bên trong __

def __init __ (self, n) -> none: có nghĩa là __init__ nên luôn luôn trả về không phải và nó có thể khá hữu ích nếu bạn vô tình trả về một cái gì đó khác với không có gì đặc biệt là nếu bạn sử dụng mypy hoặc những thứ tương tự khác.__init__ should always return NoneType and it can be quite helpful if you accidentally return something different from None especially if you use mypy or other similar things.

__ init __ bắt buộc trong Python?

Vì vậy, hàm tạo lớp cha được gọi là đầu tiên.Nhưng trong Python, không bắt buộc rằng hàm tạo lớp cha sẽ luôn được gọi là đầu tiên.Thứ tự mà phương thức __init__ được gọi cho cha mẹ hoặc lớp con có thể được sửa đổi.

Chủ đề