Что делает "mro ()"? - PullRequest
       23

Что делает "mro ()"?

110 голосов
/ 06 января 2010

В 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(). Что он делает и что означает «мро»?

Ответы [ 4 ]

189 голосов
/ 06 января 2010

Следуйте по ... ... *

>>> 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__, который определяет это имя.

79 голосов
/ 06 января 2010

mro() обозначает Порядок разрешения методов. Возвращает список типов, из которых получен класс, в порядке их поиска для методов.

mro () или __ mro __ работает только на новых классах стилей. В питоне 3 они работают без проблем. Но в python 2 эти классы должны наследоваться от объектов.

8 голосов
/ 22 марта 2016

Возможно, это покажет порядок разрешения.

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 голос
/ 05 августа 2018

Порядок разрешения будет отличаться в наследовании алмазов.

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'>)
...