Що робить "mro ()"?


Відповіді:


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
привіт, Алекс, чи є різниця між D .__ mro__ та D.mro ().
zjm1126

26
mroможе бути налаштоване метаклассом, викликаються один раз при ініціалізації класу, і результат зберігається в __mro__- см docs.python.org/library / ... .
Алекс Мартеллі

23
Чому його називають порядком вирішення методу замість порядку вирішення атрибутів ?
Bentley4

1
Так само, як сказав @Alex Martelli, і вміст python-history.blogspot.com/2010/06/… , атрибут mro слід додавати, коли використовується новий клас, як лише тоді, коли Python 2.2 MRO і Python 2.3 MRO (C3) використовуються.
Andy

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."
Рутвік Вайла

2
@RuthvikVaila: Я думаю, що ця частина лише погано заявлена. У цій публікації в блозі про історію Python, зауважує Гідо ван Россум (про схему MRO, запроваджену в Python 2.2) "Якщо будь-який клас дублювався в цьому пошуку, все, крім останнього явища, буде видалено зі списку MRO" (наголос мій ). Це означає, що це може видалити більше, ніж просто перше «згадування» про клас.
мартіно

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

але чому роздільна здатність відрізняється?
Вадим

У сценарії множинного успадкування будь-який зазначений атрибут шукається спочатку в поточному класі. Якщо його не знайдено, пошук продовжується у батьківських класах по-перше, ліво-праворуч без пошуку одного класу два рази.
Гіріш Гупта

вибачте, але я не розумію, чому в першому випадку це перейти, class B3але у другому - це class Aпісляclass B1
Вадим
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.