正如 Sergey Orshanskiy 在评论中指出的那样,编写一个装饰器来继承该__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 部分:为什么不直接使用 plain 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