Bunun ile başlayalım, Why does __init__ not get called if __new__ called with no args tekrarı değil. __new__
ve __init__
için bazı örnek kodları dikkatlice inceleyip, bulabildiğim bir açıklama yapmadım.Neden __init__ __new__ sonra çağrılmıyor __new__ SOMETIMES
temel parametreleri:
başka kütüphaneden geldiği gibi NotMine adında bir temel sınıf vardır- (Burada önemli değil, sonunda ifşa edeceğiz)
- O sınıf bir
__init__
yöntemi vardır sırayla - Ben alt sınıflarda
_parse
yöntemini geçersiz gereken bir_parse
yöntemini çağırır - hangi ı çağırma kadar bilinmemektedir yaratıyorum alt sınıf
- Ben fabrika tasarımı yöntemleri vardır biliyorum ama bu 'da türüdür biliyoruz Python logging: Why is __init__ called twice?
- I sorunlardan kaçınmak için
super
dikkatli faydalanmak çalıştık - (sonunda fazla) onları burada kullanamazsınız 'bir AbstractBaseMehtod fırsat ama bu
__new__
sonra BAZI numuneler aşağıdaki I işi diğer durumlarda işaret etmek mümkün gibi görünüyor çalışmıyor neden her açıklama için
Neyse, __init__
çağrılmalıdır yardım etmedi ve açıklamayı çıkar.
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
Eğer kodu çalıştırmak, bunu "hangi kapıyı" içinden ve ne tür ile çıkılıyor açıkladı __new__
yapılan her çağrı için olduğunu görebilirsiniz. Aynı "tip" nesneyle aynı "kapı" dan çıkabilir ve diğer bir durumda değil, bir örnekte __init__
olmalıdır. Ben "çağrı" sınıfının mro baktım ve bu sınıf (veya CCC olarak bir altkümenin) çağırmak ve denilen __init__
var beri hiçbir anlayış sunuyor.
sonu Notlar: Ben kullanıyorum NotMine
kütüphane Genshi MarkupTemplate ve Fabrika tasarım yöntemi kullanmama sebebi onların TemplateLoader inşa etme defaultClass gerekiyor. Ayrışmaya başladığıma kadar bilmiyorum, __new__
'da. Genshi yükleyicileri ve şablonlar bu çabaya değer kılan bir sürü voodoo sihir var.
Yükleyicilerinin değiştirilmemiş bir örneğini çalıştırabilirim ve şu anda her şey YALNIZCA öntanımlı olarak ABC (soyut fabrika sınıfı) sınıfını geçtiği sürece çalışır. İşler iyi çalışıyor ama bu açıklanamayan davranış daha sonra neredeyse kesin bir hatadır.
GÜNCELLEME: döndürülen nesne sonra __init__
çağrılmaz cls'ye bir "örneği" değilse Ignacio, üst çizgi soruyu çivilenmiş. Ben "constructor" çağıran (yeniden __new__
yeniden çağırır gibi yanlış ve başlattığınız yerde geri bulursunuz. Farklı bir yol almak için bir arg değiştirebilir. Bu sadece sonsuz yerine iki kez ABC.__new__
diyorsunuz demektir .Bir çalışma çözüm olarak yukarıdaki class ABC
düzenlemektir:
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
Bildirimi Son birkaç satır. __init__
, "farklı" bir sınıfsa, "farklı" sınıf hala __init__
çağrı sınıfının bir alt sınıfı olduğunda, ESPECIALLY benim için anlam ifade etmiyor. Yukarıdaki düzenlemeyi sevmiyorum ama en azından kuralları biraz daha iyi anlıyorum. the documentation itibaren
Genshi bir metaclass kullanıyor mu? Bkz. Http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python – Borealid
Hayır, Örnek kodum genshi'yi temel olarak kullanmıyor. –