我正在尝试替换派生类的__init__
方法。
但出于某种原因,虽然__init__
显示了替换函数,但调用了原始__dict__
。
如果我手动调用__init__
,则调用替换的函数...
示例代码:
class TheBase(object):
def __new__(cls, *args, **kwargs):
newInstance = super(TheBase, cls).__new__(cls)
newInstance._origInit = newInstance.__init__
newInstance.__init__ = newInstance._myInit
print "Replaced the init of {} with {} ({})".format(newInstance, newInstance._myInit, id(newInstance._myInit))
print newInstance.__dict__
return newInstance
def _myInit(self, *args, **kwargs):
print "TheBase _myInit of {} ({})".format(self, id(self.__init__))
self._origInit(*args, **kwargs)
self._afterInit()
def _afterInit(self):
print "Init has passed..."
# Do some magic here...
class MyDerived(TheBase):
def __init__(self, great=False):
TheBase.__init__(self)
print "MyDerived __init__ of {} ({})".format(self, id(self.__init__))
class MyDerived2(MyDerived):
def __init__(self):
MyDerived.__init__(self, great=True)
print "MyDerived2 __init__ of {} ({})".format(self, id(self.__init__))
sd = MyDerived()
print "--------------- manual init --------------"
sd.__init__()
结果:
Replaced the init of <__main__.MyDerived object at 0x00385390> with <bound method MyDerived._myInit of <__main__.MyDerived object at 0x00385390>> (35356224)
{'__init__': <bound method MyDerived._myInit of <__main__.MyDerived object at 0x00385390>>, '_origInit': <bound method MyDerived.__init__ of <__main__.MyDerived object at 0x00385390>>}
MyDerived __init__ of <__main__.MyDerived object at 0x00385390> (35213640)
--------------- manual init --------------
TheBase _myInit of <__main__.MyDerived object at 0x00385390> (35213640)
MyDerived __init__ of <__main__.MyDerived object at 0x00385390> (35213640)
Init has passed...
在我的真实世界项目中,我想启动一个线程(在基类中),但是直到派生类的__init__
完成后才能运行。因为这是一些重构的一部分,并且已经存在的派生类是由其他人开发的,所以我无法修改它们的代码(并在那里启动它)。
替换类中的__init__
而不是实例也是不可能的,因为有时派生类会再次派生(class MyDerived2(MyDerived):
)
有没有人知道,为什么调用原始的__init__
(以及如何避免这种情况),或者解决问题的其他方法?
答案 0 :(得分:0)
与所有魔法方法一样,__init__
在类上查找,而不是实例。
如果要自定义和/或覆盖魔术方法,则应使用metaclass。
示例:
class TheMeta(type):
def __init__(cls, name, bases, dct):
def _myInit(self, *args, **kwargs):
if type(self) is cls:
print "_myInit of {} {} ({})".format(name, self, id(self.__init__))
cls._origInit(self, *args, **kwargs)
cls._afterInit(self)
else:
cls._origInit(self, *args, **kwargs)
def _afterInit(self):
print "Init has passed..."
# Do some magic here...
cls._origInit = cls.__init__
cls.__init__ = _myInit
cls._afterInit = _afterInit
super(TheMeta, cls).__init__(name, bases, dct)
class TheBase(object):
__metaclass__ = TheMeta
class MyDerived(TheBase):
def __init__(self, great=False):
TheBase.__init__(self)
print "MyDerived __init__ of {} ({})".format(self, id(self.__init__))
class MyDerived2(MyDerived):
def __init__(self):
MyDerived.__init__(self, great=True)
print "MyDerived2 __init__ of {} ({})".format(self, id(self.__init__))
sd = MyDerived()
d2 = MyDerived2()
输出(online):
_myInit of MyDerived <__main__.MyDerived object at 0xb72d97ec> (3075484484)
MyDerived __init__ of <__main__.MyDerived object at 0xb72d97ec> (3075190908)
Init has passed...
_myInit of MyDerived2 <__main__.MyDerived2 object at 0xb72d98ec> (3075484484)
MyDerived __init__ of <__main__.MyDerived2 object at 0xb72d98ec> (3073212204)
MyDerived2 __init__ of <__main__.MyDerived2 object at 0xb72d98ec> (3075190908)
Init has passed...