“mro()”有什么作用?

时间:2010-01-06 03:04:17

标签: python method-resolution-order

django.utils.functional.py

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

我不明白mro()。它是做什么的,“mro”是什么意思?

4 个答案:

答案 0 :(得分:187)

跟着......:

>>> 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__的第一个类中。

答案 1 :(得分:79)

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

mro() __ mro __ 仅适用于新样式类。在python 3中,它们没有任何问题。但是在python 2中,这些类需要从对象继承。

答案 2 :(得分:8)

这可能会显示解决顺序。

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中删除该类的第一个提及。

答案 3 :(得分: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'>)