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

Loic Duros

在Python中,如果您使用相同的方法定义两个类,并希望这两个类成为父类,则如下所示:

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

和:

class B(object):
     def hello(self):
         print "hello from class b"

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

class C(A, B):
     def __init__(self):
         self.hello()

调用self.method()时使用的方法是属于A的方法,即继承列表中的第一个类:

>>> C()
hello from class a
<__main__.C object at 0x10571e9d0>

尽管在我所有的测试案例中似乎都是如此,但我无法在文档或在线中找到一个在任何平台和该语言实现上都安全的地方。任何人都可以肯定地说,假设列表中的第一个继承的类将始终是其他类所使用的方法(无论super().__ init __()调用如何),还是可以将我指向确认这一事实的官方文档呢?

谢谢,

巴库留

是的,可以保证,如介绍新算法以计算方法分辨率顺序(即C3线性化文档中所述

不使用此算法的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位于之后 D单调性是线性化的属性,因此在继承时不存在此类交换。如果某个类X在类Y的父的所有线性化中均在之前,则Y在最终的线性化中它也将在类之前

现在,如果我们考虑一堂课C(B1, ..., Bn)按照局部优先顺序,这些类B1, ..., Bn将在的线性化中按该顺序找到C通过单调性,我们无法BiBi自身之前找到s的子类由此可见,的线性化(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

但是,如果交换类,则可以线性化层次结构:

>>> class B(A, object): pass
... 
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

如果父类没有共同的基数(object显然不是其他基数),那么显然的线性化C(B1, ..., Bn)将以B1(除外object的线性化开始,然后将遵循B2etc的线性化,并将以:的线性化结束Bn

>>> 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'>]

Bis之间有一些通用子类时,事情开始变得怪异,在这种情况下python找到了您期望的不违反局部优先顺序和单调性的顺序,否则将引发错误。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Python和构造函数中的多重继承

来自分类Dev

python类多重继承中的方法重写

来自分类Dev

Python中的调用解析顺序具有多重继承

来自分类Dev

Python多重继承和super()

来自分类Dev

python ABC和多重继承

来自分类Dev

Java中的多重继承和方法重写问题

来自分类Dev

Scala多重继承:区分方法参数中的Iterable和PartialFunction

来自分类Dev

Python中的优雅多重继承

来自分类Dev

多重继承执行顺序

来自分类Dev

在多重继承设置中传递不同参数的Python方法

来自分类Dev

python中多重继承中的super()用法

来自分类Dev

Python调用父方法多重继承

来自分类Dev

Python调用父方法多重继承

来自分类Dev

哪个是php中多重继承的最佳方法?

来自分类Dev

在多重继承中调用超类方法

来自分类Dev

多重继承怪癖,还是Python中的错误?

来自分类Dev

带有super的python中的多重继承

来自分类Dev

带有super的python中的多重继承

来自分类Dev

多重继承和超级

来自分类Dev

多重继承和接口

来自分类Dev

多重继承和Java

来自分类Dev

多重继承的替代方法

来自分类Dev

Python ABC多重继承

来自分类Dev

Python多重继承问题

来自分类Dev

休眠中的多重继承?

来自分类Dev

休眠中的多重继承?

来自分类Dev

在多重继承的情况下,super方法如何在python中工作?

来自分类Dev

在多重继承的情况下,super方法如何在python中工作?

来自分类Dev

c ++:多态+多重继承顺序。继承顺序重要吗?