python decorator that calls super init
我正在尝试创建一个自动调用父类init的修饰符。它使用单继承,但是当我试图链接效果时,会得到一个堆栈溢出错误。有人能解释(a)为什么会发生这种情况,(b)如何实现我想要实现的目标吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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中:
1 | super().__init__() |
在python 2中:
1 | super(Parent, self).__init__() |
号
或
1 | super(Child, self).__init__() |
错误
但要回答您的直接问题,无限递归的发生是因为您如何获得父级:
1 | self.__class__.__bases__[0] |
。
无论您调用多少次
错误的方式
您可能希望找到定义当前调用的
1 2 3 4 5 6 7 | 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,请使用@yoel的版本:
1 2 3 4 5 6 7 8 9 10 11 12 | def get_class_that_defined_method(meth): if inspect.ismethod(meth): for cls in inspect.getmro(meth.__self__.__class__): if cls.__dict__.get(meth.__name__) is meth: return cls meth = meth.__func__ # fallback to __qualname__ parsing if inspect.isfunction(meth): cls = getattr(inspect.getmodule(meth), meth.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) if isinstance(cls, type): return cls return getattr(meth, '__objclass__', None) # handle special descriptor objects |
。
您现在可以重新定义您的
1 2 3 4 5 | def init(__init): def wrapper(self, *args, **kwargs): get_class_that_defined_method(__init).__bases__[0].__init__(self) __init(self) return wrapper |
。
再一次。请不要这样做。可能有许多角落的案件,我没有涵盖,将来咬你,从一切围绕埃多克斯1(6)。用