正如 Sergey Orshanskiy 在 cmets 中指出的那样,写一个装饰器来继承 __init__ 方法也很方便。
您可以编写一个装饰器来继承__init__ 方法,甚至可以自动搜索子类并装饰它们。 – 谢尔盖 Orshanskiy 2015 年 6 月 9 日 23:17
第 1/3 部分:实现
注意:实际上这仅在您想同时调用基类和派生类的__init__ 时才有用,因为__init__ 是自动继承的。请参阅此问题的先前答案。
def default_init(func):
def wrapper(self, *args, **kwargs) -> None:
super(type(self), self).__init__(*args, **kwargs)
return wrapper
class base():
def __init__(self, n: int) -> None:
print(f'Base: {n}')
class child(base):
@default_init
def __init__(self, n: int) -> None:
pass
child(42)
输出:
Base: 42
第 2/3 部分:警告
警告:如果base 本身称为super(type(self), self),这将不起作用。
def default_init(func):
def wrapper(self, *args, **kwargs) -> None:
'''Warning: recursive calls.'''
super(type(self), self).__init__(*args, **kwargs)
return wrapper
class base():
def __init__(self, n: int) -> None:
print(f'Base: {n}')
class child(base):
@default_init
def __init__(self, n: int) -> None:
pass
class child2(child):
@default_init
def __init__(self, n: int) -> None:
pass
child2(42)
RecursionError: 调用 Python 对象时超出最大递归深度。
第 3/3 部分:为什么不直接使用普通 super()?
但是为什么不直接使用安全的纯文本super()?因为它不起作用,因为新重新绑定的__init__ 来自类外,并且super(type(self), self) 是必需的。
def default_init(func):
def wrapper(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
return wrapper
class base():
def __init__(self, n: int) -> None:
print(f'Base: {n}')
class child(base):
@default_init
def __init__(self, n: int) -> None:
pass
child(42)
错误:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-9-6f580b3839cd> in <module>
13 pass
14
---> 15 child(42)
<ipython-input-9-6f580b3839cd> in wrapper(self, *args, **kwargs)
1 def default_init(func):
2 def wrapper(self, *args, **kwargs) -> None:
----> 3 super().__init__(*args, **kwargs)
4 return wrapper
5
RuntimeError: super(): __class__ cell not found