摘自python cookbook:
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
Base.__init__(self)
print('A.__init__')
class B(Base):
def __init__(self):
Base.__init__(self)
print('B.__init__')
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print('C.__init__')
如果你运行这段代码就会发现 Base.init() 被调用两次,如下所示:
>>> c = C()
Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__
>>>
用super():
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
class B(Base):
def __init__(self):
super().__init__()
print('B.__init__')
class C(A,B):
def __init__(self):
super().__init__() # Only one call to super() here
print('C.__init__')
运行这个新版本后,你会发现每个 init() 方法只会被调用一次了:
>>> c = C()
Base.__init_
B.__init__
A.__init__
C.__init__
>>>
为了弄清它的原理,我们需要花点时间解释下Python是如何实现继承的。 对于你定义的
每一个类而已,Python会计算出一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就
是一个简单的所有基类的线性顺序表。例如:
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,
<class '__main__.Base'>, <class 'object'>)
>>>
当你使用 super() 函数时,Python会在MRO列表上继续搜索下一个类。 只要每个重定义
的方法统一使用 super() 并只调用它一次, 那么控制流最终会遍历完整个MRO列表,每
个方法也只会被调用一次。 这也是为什么在第二个例子中你不会调用两次
Base.init() 的原因。
网友评论