关于python:“mro()”有什么作用?

What does “mro()” do?

django.utils.functional.py中:

1
2
3
for t in type(res).mro():  # <----- this
    if t in self.__dispatch:
        return self.__dispatch[t][funcname](res, *args, **kw)

我不明白。它做什么,"mro"是什么意思?


跟着……:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> 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为止(当然只适用于新型类)。

现在,有了多重继承…

1
2
3
4
>>> 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__中定义该名称的第一个类中。


mro()代表方法分解顺序。它返回类派生自的类型列表,按方法的搜索顺序排列。

mro()或uu mro_uuu只在新样式类上工作。在Python3中,它们的工作没有任何问题。但在Python2中,这些类需要从对象继承。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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())

答案是

1
2
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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'>)