Рубрики
Без рубрики

Динамическая природа MRO Python

Представьте себе следующие отношения классов: классная база: Def Chain (Self): возврат «База» … Помечено с Python, OOP, архитектуру.

Представьте себе следующие отношения:

class Base:
    def chain(self):
        return 'Base'


class A(Base):
    ...


class B(Base):
    def chain(self):
        return f"{super().chain()} <- B"


class C(A, B):
    pass


class D(C):
    def chain(self):
        return f"{super().chain()} <- D"

Призыв цепь В случае D приведет к следующей строке:

In [1]: d.chain()
Out[1]: 'Base <- B <- D'

Что произойдет, если следующий код работает?

In [2]: A.chain = A.chain

Потому что, верно? Теперь попробуйте позвонить d.chain () опять таки…

In [3]: d.chain()
Out[3]: 'Base <- D'

Давайте наблюдаем DLS Метод R эполюция О Рад ( MRO , порядок классов, где Python будет искать при разрешении методов и атрибутов):

In [4]: D.mro()
Out[4]: [__main__.D, __main__.C, __main__.A, __main__.B, __main__.Base, object]

При звонке D.chain () Python будет смотреть в этот список и вернуть первый экземпляр, где цепь присутствует как Член класса. В нашем примере D Реализация цепь Отказ

D.Chain В свою очередь позвонит Super (). Цепочка () Отказ Что сделает Python? Это схватит следующий класс из D и попробуйте найти цепь В этом новом списке. C не реализует это; не делает А. . B делает! Результат будет любым B.Chain Возвращает, плюс бит "<- D" Отказ

B.Chain Вызывает ли Super () снова … Мы знаем, что мы делаем. База реализует его, и больше нет Super () звонки. Так что у нас есть Base.Chain Возвращение «База» , B.Chain () Возвращение «База <- B» и D.chain () Наконец, возвращая «База <- B <- D» Отказ

Так что происходит после того, как мы сделаем A.Chain.Chain ? Почему B.Chain () игнорируется? Давайте рассмотрим, что происходит с этим. Что такое А Миро?

In [5]: A.mro()
Out[5]: [__main__.A, __main__.Base, object]

Довольно просто. Что происходит, когда вы делаете А.Чина ? Python будет смотреть на А , который не реализует это. Но База реализует его, так что это реализация, которую он собирается использовать. Но Что происходит, когда мы делаем задание?

Python оценивает это присвоение право налево: A.Chain.Chain Тогда означает «найти цепочку для«, которая возвращается Base.Chain Отказ Тогда, Python будет эффективно создать новый элемент в классе a dimed цепь Действительно

Давайте вернемся к D’S MRO:

[__main__.D, __main__.C, __main__.A, __main__.B, __main__.Base, object]

То, как эти классы были построены, А Члены будут проверены до B Действительно Что это значит для постановления разрешения? Когда D.chain () звонки Super (). Цепочка () Теперь теперь будет захватить недавно добавленный член A и назовите это. И от А точка зрения, реализация такая же, как Base.Chain , у кого нет Super () вызов! 🤯

Это происходит из-за динамической природы Python. Запись для Super () В документации Python Имеет удивительное описание этой проблемы и как это уникальное использование случаев из-за природы Python.

Многократная функция наследования Python, плюс ее динамическая природа, сделайте ее, чтобы реальный порядок разрешения метода и иерархии класса известны только во время выполнения и могут измениться в любое время во время срока службы приложения.

Конструкции классов должны быть Сотрудничество Отказ Приведенный выше пример имеет много вопросов, Но есть простой набор правил, которые помогают проектировать совместные классы :

  • Методы, называемые Super () должны существовать
  • Способы называются и их реализации необходимо иметь соответствующий аргумент подписи
  • Каждое вхождение метода необходимо использовать Super ()

Точка вот что фактическая реализация метода, называемого Super () Известен только во время выполнения и не может быть легко определен статически.

Разработайте свои классы совместно и следите за мутациями в классах в вашем среде выполнения.

Хотите узнать больше о MRO Python Mro? Эта удивительная статья в документах Python вводит, как работает алгоритм после версии 2.3. Проверьте это Действительно

Это мой первый dev.to post. Пожалуйста, дайте мне знать, если есть что-то, что я могу сделать, чтобы сделать это лучше!

фото Адам Шмигильский на Бессмысленно

Оригинал: “https://dev.to/rbusquet/the-dynamic-nature-of-python-s-mro-22on”