Python与多重继承中的方法顺序

Python与多重继承中的方法顺序,python,oop,inheritance,multiple-inheritance,method-resolution-order,Python,Oop,Inheritance,Multiple Inheritance,Method Resolution Order,在Python中,如果使用相同的方法定义两个类,并打算将这两个类作为父类,如下所示: class A(object): def hello(self): print "hello from class a" 以及: 定义子类并按A和B的顺序添加两个父类时: class C(A, B): def __init__(self): self.hello() 调用self.method()时使用的方法是属于的方法,或继承列表中的第一个类: &

在Python中,如果使用相同的方法定义两个类,并打算将这两个类作为父类,如下所示:

class A(object):
     def hello(self):
         print "hello from class a" 
以及:

定义子类并按A和B的顺序添加两个父类时:

class C(A, B):
     def __init__(self):
         self.hello()
调用self.method()时使用的方法是属于的方法,或继承列表中的第一个类:

>>> C()
hello from class a
<__main__.C object at 0x10571e9d0>
>>C()
a班同学你好
虽然这在我所有的测试用例中似乎都是正确的,但我在文档或在线文档中找不到一个地方表明它在任何平台和语言实现中都是安全的。任何人都可以确认是否可以安全地假设列表中的第一个继承类将始终是用于其他类的方法(不管super()。\uuuu init\uuuuu()调用等),或者向我指出一份官方文档来确认这一点


谢谢,

以下是详细解释的方法解析顺序:

Python文档(术语表)实际上指出了这一点

根据我的经验,跨实现使用它是安全的。您可以使用
mro()
检查分辨率顺序

A类(对象):
def你好(self):
打印“来自A的你好”
B类(对象):
def你好(self):
打印“hello from B”
丙类(甲、乙类):
定义初始化(自):
self.hello()
>>>C()
A:你好
>>>打印C.\U mro__
(, , )
>>>打印C.mro()
[, , ]

是的,如介绍新算法以计算方法分辨率顺序(即)的中所述,它是有保证的

对于
mro
不使用此算法的实现,并不真正符合python语言(版本2.3+)。AFAIK所有当前实现都使用C3线性化


C3线性化满足局部优先顺序和单调性。局部优先顺序意味着类
C(B1,…,Bn)
将在其
mro
中按基类
Bi
在继承列表中列出的顺序排列

用一个例子也许可以更好地解释单调性:

>>> class A(object): pass
>>> class B(object): pass
>>> class C(object): pass
>>> class D(object): pass
>>> class E(object): pass
>>> class K1(A,B,C): pass
>>> class K2(D,B,E): pass
>>> class K3(D,A):   pass
>>> class Z(K1,K2,K3): pass
python2.2的旧mro(不是单调的),这些是上述类的线性化:

L[A] = A O
L[B] = B O
L[C] = C O
L[D] = D O
L[E] = E O
L[K1]= K1 A B C O
L[K2]= K2 D B E O
L[K3]= K3 D A O
L[Z] = Z K1 K3 A K2 D B C E O
# in current versions of python (2.3+):
# L[Z] = Z K1 K2 K3 D A B C E O
在这里您可以看到,在
Z
的线性化中,类
A
位于
D
之前,而在
K3
的线性化中,类
A
位于
D
之后。单调性是线性化的特性,因此在继承时不存在此类交换。如果在类的父类的所有线性化中,类
X
在类
Y
之前,那么在最终线性化中,它也将在类
Y
之前

现在,如果我们考虑一个类<代码> C(B1,…,BN)< /代码>。通过局部优先顺序,类

B1,…,Bn
将在
C
的线性化中按该顺序找到。通过单调性,我们无法在
Bi
本身之前找到
Bi
的子类。由此可知,
C
的线性化(如果存在)必须从
C
B1
开始

请注意,在某些情况下,您无法计算线性化,python会抱怨,例如:

>>> class A(object):pass
... 
>>> class B(object, A): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, A

当您在
Bi
s之间有一些公共子类时,事情开始变得奇怪。在这种情况下,python会找到您期望的不违反局部优先顺序和单调性的顺序,或者它会引发错误。

Search
MRO
方法解析顺序
。请阅读。
L[A] = A O
L[B] = B O
L[C] = C O
L[D] = D O
L[E] = E O
L[K1]= K1 A B C O
L[K2]= K2 D B E O
L[K3]= K3 D A O
L[Z] = Z K1 K3 A K2 D B C E O
# in current versions of python (2.3+):
# L[Z] = Z K1 K2 K3 D A B C E O
>>> class A(object):pass
... 
>>> class B(object, A): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, A
>>> class B(A, object): pass
... 
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> class A(object): pass
... 
>>> class B(object): pass
... 
>>> class A1(A): pass
... 
>>> class A2(A1): pass
... 
>>> class B1(B): pass
... 
>>> class C(object): pass
... 
>>> class C1(C): pass
... 
>>> class C2(C1):pass
... 
>>> class C3(C2): pass
... 
>>> class D(A2, B1, C3): pass
... 
>>> D.mro()
[<class '__main__.D'>, <class '__main__.A2'>, <class '__main__.A1'>, <class '__main__.A'>, <class '__main__.B1'>, <class '__main__.B'>, <class '__main__.C3'>, <class '__main__.C2'>, <class '__main__.C1'>, <class '__main__.C'>, <class 'object'>]