Python和多重继承中的方法顺序 [英] Python and order of methods in multiple inheritance

查看:119
本文介绍了Python和多重继承中的方法顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Python, if you define two classes with the same method and intend for those two classes to be parent classes, as:

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

和:

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

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

when you define the child class and add the two parent classes in the order A and B:

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

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

the method that is used when calling self.method() is the one belonging to A, or the first class in the list of inheritance:

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

虽然在我的所有测试用例中似乎都是如此,但我找不到docs或online,它实际上对任何平台和语言的实现都是安全的。任何人都可以确认可以安全地假设列表中的第一个继承类将始终是使用的方法(不管super().__ init __()调用等)或指向我确认这个的官方文档?

While this seems to be true in all my test cases, I can't find a place in the docs or online that it is actually safe across any platform and implementation of the language. Can anyone either confirm it is safe to assume the first inherited class in the list will always be the method used over the others (regardless of super().__init__() calls etc) or point me towards an official documentation confirming this?

谢谢,

推荐答案

是的,保证如< a href =http://www.python.org/download/releases/2.3/mro/ =nofollow>文档引入了新算法来计算方法解析顺序( C3线性化)。

Yes it is guaranteed as described in the document that introduced the new algorithm to compute the method resolution order (which is C3 linearization).

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

Implementations that don't use this algorithm for their mro don't really conform to the python language (version 2.3+). AFAIK all current implementation do use C3 linearization.

C3线性化满足本地优先顺序和单调性。本地优先顺序意味着类 C(B1,...,Bn)将在其 mro 基础中-classes Bi 按继承列表中列出的顺序。

C3 linearization satisfies the local precedence ordering and monotonicity properties. local precedence ordering means that a class C(B1, ..., Bn) will have in its mro the base-classes Bi in the order they were listed in the inheritance list.

单调性可能更好地用一个例子来解释:

Monotonicity is probably better explained with an example:

>>> 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(这是 not monotonic),这些是上述类的线性化:

The old mro for python2.2 (which is not monotonic), these are the linearizations of the above classes:

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 的线性化过程中, <$ em $ c> C 后出现。单调性是线性化的特性,使得在继承时没有这种交换。如果类 X 在类的父级的所有线性化中在类 Y 之前,那么它也将在类<最终线性化中code> Y 。

Here you can see that, in the linearization of Z, the class A comes before D, while in the linearization of K3 it comes after D. Monotonicity is the property of a linearization such that there are no swaps of this kind when inheriting. If a class X precedes class Y in all linearization of the parents of a class, then it will also precedes class Y in the final linearization.

现在,如果我们考虑一个类 C(B1, ...,Bn)。按照本地优先顺序,将在 C 的线性化中按顺序找到类 B1,...,Bn 。通过单调性,我们无法在 Bi 之前找到 Bi 的子类。由此可见 C 的线性化(如果存在)必须以 C 开头B1

Now, if we consider a class C(B1, ..., Bn). By local precedence order the classes B1, ..., Bn will be found in that order in the linearization of C. By monotonicity we cannot find subclasses of Bis before the Bi itself. From this follows that the linearization of C, if it exists, must start with C and B1.

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

Note that in some cases you can't compute the linearization, and python will complain, for example:

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

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

However if you swap the classes it is possible to linearize the hierarchy:

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

如果父类没有共同基础(显然除了对象之外),那么很明显 C(B1,...,Bn)的线性化将从 B1 的线性化开始(除了 object ),然后将跟随 B2 等的线性化,它将以 Bn :

If parent classes have no common base (other then object obviously), then it's clear that the linearization of C(B1, ..., Bn) will start with the linearization of B1 (except for object), then will follow the linearization of B2 etc and it will end with the linearization of 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'>]

当你在 Bi 之间有一些常见的子类时,事情开始变得奇怪了,在这种情况下,python会找到你期望的顺序不违反本地优先顺序和单调性,否则会引发错误。

Things start to get weird when you have some common subclasses between the Bis in which case either python finds the order that you'd expect that doesn't violate local precedence order and monotonicity or it will raise an error.

这篇关于Python和多重继承中的方法顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆