1 Востаннє редагувалося Bartash (26.12.2017 18:17:53)

Тема: Method Resolution Order (MRO) in Python

Доброго часу доби.

Ця коротка стаття покликана пояснити сутність MRO у Пітоні без поглиблень у теорію.

Як відомо, ключова теорема проблема MRO (Method Resolution Order) демонструється прикладом:

class Base: pass

class A(Base): pass

class B(Base): pass

class B1:
    def foo(): pass

class C(A, B[, B1]): pass

C().foo()  # will call C->A->Base->B->Base[->B1]

Потенційні граблі такі:
1. Виклик Base.foo() раніше, ніж B.foo (якщо вона є), що некоректно з погляду нормальної побудови наслідування.
2. Подвійний виклик Base.foo(), якщо A та B не містять потрібного методу (надлишкова перевірка).

І так було аж до виходу Пітона 2.3. Тоді розробники мови винайшли прекрасний спосіб зберегти концептуальну ідею і вирішити обидві проблеми:

# Inheritance from object is required for Python 2. Python 3 doesn't support old style.
class Base(object): pass

class A(Base): pass

class B(Base): pass

class B1:
    def foo(): pass

class C(A, B[, B1]): pass

C().foo()  # will call C->A->B->Base[->B1]

Класи C,A,B,Base утворили ромб зі спільним "батьком" Base.

Окрім того, C, B1 також мають замкнену структуру з "батьком" object. У межах кожного такого "ромбу" пошук іде так само вгору, але не до кінця, а до вершини ромбу. Ця фіча значно спростила створення ієрархій класів і стала єдиним стандартом у третьому Пітоні.

Такий от MROмб від Гвідо і Ко.

I belong to the Dead Generation.
Подякували: 0xDADA11C7, NagarD, ping, /KIT\, Altair8800, leofun016

2

Re: Method Resolution Order (MRO) in Python

1. Виклик Base.foo() раніше, ніж B.foo

Як варіант, можна записати першим В, а другим А - виглядає як костиль в порівнянні з концепцією ромбу, та все ж

Подякували: Bartash1