正如Sergey Orshanskiy在评论中指出的那样,编写一个装饰器来继承
__init__
方法也很方便。
你可以编写一个装饰器来继承__init__
方法,甚至可以自动搜索子类并对其进行装饰。 - Sergey Orshanskiy Jun 9 '15 at 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
第二部分/三部分:警告
警告:如果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对象时超出了最大递归深度。
第三部分:为什么不只使用普通的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
__init__
方法,甚至可以自动搜索子类并对其进行装饰。 - Sergey Orshanskiysuper()
的调用。 - user26742873