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

Скажем, у меня есть класс A, Bи C.

Классы Aи Bявляются классами примесей для класса C.

class A( object ):
    pass
class B( object ):
    pass
class C( object, A, B ):
    pass

Это не будет работать при создании экземпляра класса C. Мне пришлось бы удалить objectиз класса C, чтобы заставить его работать. (Иначе у вас будут проблемы с MRO).

TypeError:Ошибка при вызове баз метаклассов
Невозможно создать согласованное разрешение метода
заказ (ТОиР)для баз Б, объекта, А

Однако мой случай немного сложнее. В моем случае класс C— это сервер , где Aи Bбудут плагинами, загружаемыми при запуске. Они находятся в своей собственной папке.

У меня также есть класс с именем Cfactory. В Cfactory у меня есть метод __new__, который создаст полнофункциональный объект C. В методе __new__я ищу плагины, загружаю их с помощью __import__и затем назначаю ихC.__bases__ += (loadedClassTypeGoesHere, )

Таким образом, следующая возможность:(сделала его довольно абстрактным)

class A( object ):
    def __init__( self ): pass
    def printA( self ):   print "A"
class B( object ):
    def __init__( self ): pass
    def printB( self ):   print "B"
class C( object ):
    def __init__( self ):  pass
class Cfactory( object ):
    def __new__( cls ):
        C.__bases__ += ( A, )
        C.__bases__ += ( B, )
        return C()

Это снова не будет работать и снова приведет к ошибкам MRO:

TypeError :Невозможно создать согласованное разрешение метода
закажите (MRO)для базового объекта, A

Легко исправить это, удалив базовый класс objectиз Aи B. Однако это сделает их объектами старого-стиля, которых следует избегать, когда эти плагины запускаются автономно-отдельно (, что должно быть возможно с помощью UnitTest)

Другое простое решение — удаление objectиз Cно это также сделает его классом в старом стиле -и C.__bases__будет недоступен, поэтому я не могу добавить дополнительные объекты в базуC

Какое было бы хорошее архитектурное решение для этого и как бы вы это сделали? что-то вроде этого?На данный момент я могу жить со старыми-классами для самих плагинов. Но я предпочитаю не использовать их.

10
задан Daan Timmer 9 October 2015 в 07:53
поделиться