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是服务器在那里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()
Run Code Online (Sandbox Code Playgroud)
这将再次起作用,并将再次给出MRO错误:
TypeError:无法
为基础对象A 创建一致的方法解析顺序(MRO)
一个简单的解决方法是object从A和中删除基类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)