“ mro()”有什么作用?


Answers:


211

跟着...:

>>> class A(object): pass
... 
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
... 
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>> 

只要我们具有单一继承,__mro__它就只是该类的元组:类,其基础,其基础的基础,依此类推object(当然,仅适用于新型类)。

现在,具有多重继承...:

>>> class D(B, C): pass
... 
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

...您还可以确保,在中__mro__,没有类被重复,并且没有类在其祖先之后出现,除了首先进入相同多重继承级别的类(如本例中的B和C)之外,__mro__左到右。

从类的实例(而不是方法)获得的每个属性在概念上都会沿进行查找__mro__,因此,如果祖先中有多个类定义了该名称,则可以告诉您在哪里可以找到该属性-在第一个类中在__mro__定义该名称。


9
嗨,alex,D .__ mro__和D.mro()有什么区别。
zjm1126 '01

26
mro可以由元类自定义,在类初始化时被调用一次,结果存储在__mro__-请参阅docs.python.org/library/…
亚历克斯·马丁里

23
为什么将其称为方法解析顺序而不是属性解析顺序
Bentley13年

1
就像@Alex Martelli所说的以及python-history.blogspot.com/2010/06/…的内容 一样,使用新类时应添加mro属性,仅当Python 2.2 MRO和Python 2.3 MRO(C3)时才应添加被使用。
2014年

82

mro()代表方法解析顺序。它以搜索方法的顺序返回类派生的类型的列表。

mro()__mro__仅适用于新样式类。在python 3中,它们可以正常工作。但是在python 2中,这些类需要从继承object


10

这也许会显示解决的顺序。

class A(object):
    def dothis(self):
        print('I am from A class')

class B(A):
    pass

class C(object):
    def dothis(self):
        print('I am from C class')

class D(B, C):
    pass

d_instance= D()
d_instance.dothis()
print(D.mro())

和响应将是

I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]

该规则是深度优先的,在这种情况下,其含义是D,B,A,C。

在搜索继承的类时,Python通常使用深度优先的顺序,但是当两个类从同一个类继承时,Python将从mro中删除对该类的首次提及。


1
如您所见,顺序为D,B,A,C
Stryker

1
“ Python从mro中删除该类的第一个提及”是什么意思?
Ruthvik Vaila

2
@RuthvikVaila:我认为这部分陈述得不好。在有关Python历史的博客文章中,Guido van Rossum评论(关于Python 2.2中引入的MRO方案)“如果此搜索中有任何重复的类,则除最后一次出现的所有类都将从MRO列表中删除”(强调我的)。这意味着它可以消除的不只是该类的第一个“提法”。
martineau

1

钻石继承的解决顺序将有所不同。

class A(object):
    def dothis(self):
        print('I am from A class')


class B1(A):
    def dothis(self):
        print('I am from B1 class')
    # pass


class B2(object):
    def dothis(self):
        print('I am from B2 class')
    # pass


class B3(A):
    def dothis(self):
        print('I am from B3 class')


# Diamond inheritance
class D1(B1, B3):
    pass


class D2(B1, B2):
    pass


d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)


d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

但是为什么分辨率不同?
Vadim '18年

在多继承方案中,将在当前类中首先搜索任何指定的属性。如果未找到,则搜索将以深度优先,从左到右的方式继续进入父类,而无需两次搜索相同的类。
Girish Gupta

抱歉,但我不明白为什么在第一种情况下它去class B3,但在第二种情况下的转到class Aclass B1
瓦迪姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.