调用超级init的python decorator
我正在尝试制作一个自动调用父类init的装饰器。它与单一继承一起工作,但当我尝试链接效果时,会出现堆栈溢出错误。有人能解释(a)为什么会发生这种情况,以及(b)如何实现我想要实现的目标吗调用超级init的python decorator,python,reflection,decorator,Python,Reflection,Decorator,我正在尝试制作一个自动调用父类init的装饰器。它与单一继承一起工作,但当我尝试链接效果时,会出现堆栈溢出错误。有人能解释(a)为什么会发生这种情况,以及(b)如何实现我想要实现的目标吗 def init(__init): def wrapper(self, *args, **kwargs): self.__class__.__bases__[0].__init__(self) __init(self) return wrapper class
def init(__init):
def wrapper(self, *args, **kwargs):
self.__class__.__bases__[0].__init__(self)
__init(self)
return wrapper
class Base:
def __init__(self):
print("base init")
class Parent(Base):
@init
def __init__(self):
print("parent init")
class Child(Parent):
@init
def __init__(self):
print("child init")
a = Parent() #works
#c = Child() #stack overflow
正确的方法 正确的方法是直接在代码中调用父初始值设定项。在Python 3中:
super().__init__()
在Python 2中:
super(Parent, self).__init__()
或
错误
不过,为了回答您眼前的问题,无限递归的发生是因为您如何获得父对象:
self.__class__.__bases__[0]
self
将不会停止作为Child
的实例,无论您调用wrapper
函数多少次。您最终会无限期地调用父类。\uuuu init\uuuu(self)
,因为父类从未更改
走错了路
您可能希望找到定义当前正在调用的\uuuu init\uuu
方法的类,并获取该方法的父类@AlexMartelli在其中提供了一个函数,用于执行此操作或Python,我在这里逐字复制:
import inspect
def get_class_that_defined_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__:
return cls
return None
如果您使用的是Python 3,请改用:
再说一遍。请不要这样做。可能有很多我没有提到的角落案例会来咬你,从
\uuuuuu base\uuuuu0]
开始。只需使用super
即可。无论如何,这是一个经过深思熟虑的同一想法的更好版本。正确的方法
正确的方法是直接在代码中调用父初始值设定项。在Python 3中:
super().__init__()
在Python 2中:
super(Parent, self).__init__()
或
错误
不过,为了回答您眼前的问题,无限递归的发生是因为您如何获得父对象:
self.__class__.__bases__[0]
self
将不会停止作为Child
的实例,无论您调用wrapper
函数多少次。您最终会无限期地调用父类。\uuuu init\uuuu(self)
,因为父类从未更改
走错了路
您可能希望找到定义当前正在调用的\uuuu init\uuu
方法的类,并获取该方法的父类@AlexMartelli在其中提供了一个函数,用于执行此操作或Python,我在这里逐字复制:
import inspect
def get_class_that_defined_method(meth):
for cls in inspect.getmro(meth.im_class):
if meth.__name__ in cls.__dict__:
return cls
return None
如果您使用的是Python 3,请改用:
再说一遍。请不要这样做。可能有很多我没有提到的角落案例会来咬你,从
\uuuuuu base\uuuuu0]
开始。只需使用super
即可。无论如何,这是一个经过深思熟虑的版本。看看第二种情况下的自我是什么。它将始终是Parent
,因为self
始终是Child
的一个实例,无论您对它调用什么方法。您希望对包含您正在调用的\u init
的类进行引用。这将确保您的递归最终终止。此装饰程序的实际意义是什么???不要费心尝试使此装饰程序工作。这将是一次充满陷阱的艰难旅程。只需像其他人一样在构造函数中调用父级\uuuuu init\uuuu
。反正只比键入@init
长几个字符。@Rawing。我希望我在回答中抓住了你的情绪。看看第二种情况是什么。它将始终是Parent
,因为self
始终是Child
的一个实例,无论您对它调用什么方法。您希望对包含您正在调用的\u init
的类进行引用。这将确保您的递归最终终止。此装饰程序的实际意义是什么???不要费心尝试使此装饰程序工作。这将是一次充满陷阱的艰难旅程。只需像其他人一样在构造函数中调用父级\uuuuu init\uuuu
。反正只比键入@init
长几个字符。@Rawing。我希望我的回答能抓住你的感情。