如何动态添加mixins作为基类而不会出现MRO错误?

Daa*_*mer 10 python architecture class method-resolution-order

说我有一节课A,B而且C.

Class A和class B都是mixin类C.

class A( object ):
    pass
class B( object ):
    pass
class C( object, A, B ):
    pass
Run Code Online (Sandbox Code Playgroud)

这在实例化类C时不起作用.我将不得不object从类C中删除它以使其工作.(否则你会得到MRO问题).

TypeError:调用元类库时出错
无法
为基础B,对象,A 创建一致的方法解析顺序(MRO)

但是,我的情况有点复杂.在我的案例类C服务器在那里AB将是在启动时加载的插件.它们驻留在自己的文件夹中.

我也有一个名为的类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()
Run Code Online (Sandbox Code Playgroud)

这将再次起作用,并将再次给出MRO错误:

TypeError:无法
为基础对象A 创建一致的方法解析顺序(MRO)

一个简单的解决方法是objectA和中删除基类B.然而,这将使它们成为旧式对象,当这些插件独立运行时应该避免(这应该是可能的,UnitTest明智的)

另一个简单的解决方法是删除object,C但这也将使它成为旧式类,并且C.__bases__将不可用因此我无法添加额外的对象到基础C

什么是一个很好的架构解决方案,你会怎么做这样的事情?现在我可以使用插件本身的旧式类.但我宁愿不使用它们.

agf*_*agf 11

可以这样想想 - 你希望mixins覆盖一些行为object,所以它们需要object在方法解析顺序之前.

所以你需要改变基数的顺序:

class C(A, B, object):
    pass
Run Code Online (Sandbox Code Playgroud)

由于这个bug,你不需要C直接从对象继承就能正确分配__bases__,而工厂真的可以只是一个函数:

class FakeBase(object):
    pass

class C(FakeBase):
    pass

def c_factory():
    for base in (A, B):
        if base not in C.__bases__:
            C.__bases__ = (base,) + C.__bases__
    return C()
Run Code Online (Sandbox Code Playgroud)