Как динамически изменять базовый класс экземпляров во время выполнения?

В этой статье есть фрагмент, показывающий использование __bases__ для динамического изменения иерархии наследования некоторого кода Python путем добавления класса в существующую коллекцию классов классов, от которых он наследуется.Хорошо, это трудно читать, код, вероятно, понятнее:

class Friendly:
    def hello(self):
        print 'Hello'

class Person: pass

p = Person()
Person.__bases__ = (Friendly,)
p.hello()  # prints "Hello"

То есть Person не наследуется от Friendly на исходном уровне, а скорее это отношение наследования добавляется динамически во время выполнения путем изменения атрибута __bases__ класса Person. Однако, если вы измените Friendly и Person на новые классы стиля (путем наследования от объекта), вы получите следующую ошибку:

TypeError: __bases__ assignment: 'Friendly' deallocator differs from 'object'

Немного поиска в Google по этому вопросу кажется указывают на некоторую несовместимость между классами нового и старого стиля в отношении изменения иерархии наследования во время выполнения. В частности: «Объекты класса нового стиля не поддерживают присвоение их атрибуту bases».

Мой вопрос: можно ли заставить приведенный выше пример Friendly/Person работать, используя классы нового стиля в Python 2.7+, возможно, с помощью атрибута __mro__?

Отказ от ответственности: я полностью понимаю, что это неясный код. Я полностью понимаю, что в реальном производственном коде подобные трюки, как правило, граничат с нечитаемостью, это чисто мысленный эксперимент, и для фанзиков нужно узнать что-то о том, как Python справляется с проблемами, связанными с множественным наследованием.

68
задан Alexey 3 May 2019 в 15:51
поделиться