类继承
所有的类都继承自 object。被继承的类称为基类(或父类,超类),继承者称为子类。
对于多数应用来说,在最简单的情况下,你可以认为搜索从父类所继承属性的操作是深度优先、从左至右的,当层次结构中存在重叠时不会在同一个类中搜索两次。
class A():
def show(self):
print('A')
class B(A):
pass
class C():
pass
class D():
def show(self):
print('D')
class E(C, B, D): # C -> B -> A -> D
pass
e = E()
e.show()
A
真实情况比这个更复杂一些;方法解析顺序会动态改变以支持对 super() 的协同调用。这种方式在某些其他多重继承型语言中被称为 后续方法调用,它比单继承型语言中的 super 调用更强大。
动态改变顺序是有必要的,因为所有多重继承的情况都会显示出一个或更多的菱形关联(即至少有一个父类可通过多条路径被最底层类所访问)。例如,所有类都是继承自 object,因此任何多重继承的情况都提供了一条以上的路径可以通向 object。为了确保基类不会被访问一次以上,动态算法会用一种特殊方式将搜索顺序线性化,保留每个类所指定的从左至右的顺序,只调用每个父类一次,并且保持单调(即一个类可以被子类化而不影响其父类的优先顺序)。
总而言之,这些特性使得设计具有多重继承的可靠且可扩展的类成为可能。
一个基类如果有 __init__()
方法,则其所派生的类如果也有 __init__()
方法,就必须显式地调用它以确保实例基类部分的正确初始化:
class A:
def __init__(self):
self.a = 'A'
def f(self):
print(self.a)
class B(A):
def __init__(self):
self.b = 'B'
b = B()
b.f() # 基类未初始化,属性 a 不可调用
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-cda60db4451f> in <module>
11
12 b = B()
---> 13 b.f()
<ipython-input-5-cda60db4451f> in f(self)
4
5 def f(self):
----> 6 print(self.a)
7
8 class B(A):
AttributeError: 'B' object has no attribute 'a'
A.__init__(b) # 将实例 b 传给 A 初始化
b.f()
A
# 或者直接用 super()
class A:
def __init__(self):
self.a = 'A'
def f(self):
print(self.a)
class B(A):
def __init__(self):
super().__init__()
self.b = 'B'
b = B()
b.f()
A