讓我從這開始不是重複的 Why does __init__ not get called if __new__ called with no args。我試圖仔細地構建一些__new__
和__init__
的示例代碼,我沒有找到解釋。爲什麼__init__在__new__之後沒有被調用有時
基本參數:
- 有一個叫NotMine因爲它從另一個庫基類(我將在月底公佈,在這裏並不重要)
- 那類有一個
__init__
方法隨後調用_parse
方法 - 我需要重寫在子類中的方法
_parse
- 其子類我創建不知道,直到調用
- 我知道有工廠的設計方法,但我不能(在末尾更多)在這裏使用它們
- 我曾試圖彌補謹慎使用
super
避免問題 Python logging: Why is __init__ called twice? - 我知道這也是「之類的「一個AbstractBaseMehtod機會,但沒有幫助
__new__
後和爲什麼一些樣品下面不工作我似乎能夠指向做工作,其他情況下每解釋
反正__init__
應該叫和排除解釋。
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
如果你執行的代碼,你可以看到,對於每次調用__new__
它宣佈「這門」,它是通過與什麼類型的退出。我可以用相同的「類型」對象退出相同的「門」,並在一種情況下調用__init__
而不調用另一種。我已經看過「調用」類的mro,因爲我可以調用該類(或CCC中的子類)並調用__init__
,所以沒有提供任何見解。
完備註:我使用 的NotMine
庫是Genshi MarkupTemplate並沒有使用廠設計方法的原因是,他們的TemplateLoader需要defaultClass建設。我不知道,直到我開始解析,我在__new__
。 genshi裝載機和模板有很多很酷的巫術魔法,這使得這個值得付出努力。
我可以運行它們的加載程序的未修改實例,目前一切正常,只要我將ABC(抽象工廠類)作爲默認類傳遞即可。事情運作良好,但這種無法解釋的行爲後來幾乎是某種錯誤。
UPDATE: 伊格納西奧,釘頂線問題,如果返回的對象不是一個CLS然後__init__
不叫「實例」。我發現調用「構造函數」(例如AA(args..)
是錯誤的,因爲它會再次調用__new__
,並且您馬上回到了開始的位置。您可以修改一個arg以採取不同的路徑,這意味着您撥打ABC.__new__
兩次而不是無限。一個工作解決方案是編輯class ABC
以上爲:
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
請注意最後幾行。如果它是一個「不同」類對我沒有意義,請致電__init__
,特別是當「不同」類仍然是調用__init__
的類的子類時。我不喜歡上面的編輯,但現在我得到的規則好一點。
Genshi是否使用元類?請參閱http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python – Borealid 2012-02-20 19:25:27
不,我的示例代碼不使用genshi作爲基礎。 – 2012-02-20 19:32:21