Why is __init__ not called after __new__ SOMETIMES
让我从这开始,这不是重复的如果在没有参数的情况下调用了new,为什么不调用init?我试着为
基本参数:
- 有一个名为notmine的基类,因为它来自另一个库(我将在最后披露,这里不重要)
- 该类有一个
__init__ 方法,该方法反过来调用_parse 方法 - 我需要在子类中重写
_parse 方法 - 在调用之前,我要创建的子类是未知的
- 我知道有工厂设计方法,但我不能在这里使用(更多在最后)
- 我试着谨慎使用
super 以避免python logging:为什么调用了两次? - 我知道这也是"某种"抽象的机会,但这没有帮助
不管怎样,应该在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 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 |
如果您执行代码,您可以看到对
结束注释:我使用的
我可以运行他们的加载器的一个未修改的实例,并且只要我将abc(抽象类工厂)类作为默认类传递,当前一切都可以工作。事情进展顺利,但这种无法解释的行为后来几乎成了某种缺陷。
更新:Ignacio确定了顶行问题,如果返回的对象不是"cls的实例",则不会调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 |
注意最后几行。如果它是一个"不同"的类,那么不调用
从文档:
If
__new__() does not return an instance of cls, then the new instance’s__init__() method will not be invoked.
这是一个让
这只是我的两美分,但是你为什么不genshi鸭打字使用Python提供一类behaves样东西?
我把genshi快速看源代码和唯一的要求,我看到在"阶级"的templateloader参数是它是在给定的参数调用。
我认为它会更容易在一个模拟的类工厂函数返回的是实际创建的实例。