假设我有一个类 A
, B
和 C
.
类 A
和 B
都是 Class C
的混合类.
class A( object ):
pass
class B( object ):
pass
class C( object, A, B ):
pass
这在实例化 C 类时不起作用。我将不得不删除 object
来自 C 类使其工作。 (否则你会遇到 MRO 问题)。
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases B, object, A
但是,我的情况有点复杂。在我的案例中类 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: Cannot create a consistent method resolution
order (MRO) for bases object, A
解决这个问题的一个简单方法是删除 object
来自 A
的基类和 B
.然而,这将使它们成为旧式对象,当这些插件独立运行时应该避免这种情况(这应该是可能的,明智的 UnitTest)
另一个简单的修复方法是删除 object
来自 C
但这也将使它成为一个旧式类和C.__bases__
将不可用,因此我无法将额外的对象添加到 C
的基础上
什么是好的架构解决方案?您将如何做这样的事情?现在我可以接受插件本身的旧式类。但我宁愿不使用它们。
最佳答案
这样想——您希望 mixins 覆盖 object
的某些行为,因此它们需要在方法解析顺序中位于 object
之前。
所以你需要改变碱基的顺序:
class C(A, B, object):
pass
由于this 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()
关于python - 如何在不出现 MRO 错误的情况下动态添加 mixin 作为基类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10132679/