转载须注明出处:简书@Orca_J35
可参考另外两则笔记:方法解析顺序(MRO) | super()
子类中的方法会覆盖父类中的同名方法,如果需要调用父类中的方法,可以采用以下两种方式:
-
通过父类名称来调用父类中方法:
<parent class name>.<method name>(self, <other arguments>)
-
构造一个 super 对象,并通过该对象调用父类中的方法。这种方法的优点在于无需显式引用父类,从而使代码更容易维护;并且在"钻石形"多继承的类层次结构中可避免重复调用父类中的方法。
在单继承的类层次结构中,上述两种方法并没有太显著的区别。super
的优点在于无需显式引用父类,从而使代码更容易维护。比如,在子类中调用父类的 __init__()
方法,以确保正确初始化:
class Base:
def __init__(self, arg):
print('Base.__init__')
class A(Base):
def __init__(self, arg):
Base.__init__(self, arg) # 等效于 super().__init__(arg)
print('A.__init__')
在"钻石形"多继承的类层次结构中,如果直接引用父类名称,则可能会重复调用父类中的方法。比如,考虑如下的情况:
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__
>>>
两次调用 Base.__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__
>>>
为了弄清 super()
的原理,这里需要补充一个知识点:方法解析顺序(MRO) 。
网友评论