如何动态地添加混入作为基类没有得到MRO错误? [英] How do I dynamically add mixins as base classes without getting MRO errors?
问题描述
说我有一个类 A
, B
和 C
。
类 A
和 B
都混入类类 C
。
class A( object ):
pass
class B( object ):
pass
class C( object, A, B ):
pass
实例类C.时,这将不工作,我必须从C类中删除对象
,使其工作。 (否则你会得到MRO问题)。
This will not work when instantiating class C. I would have to remove object
from class C to make it work. (Else you'll get MRO problems).
类型错误:调用元类基地时出现错误结果
无法创建一个一致的方法解析结果
顺序(MRO)为基地B,对象,A
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases B, object, A
不过,我的情况有点复杂。在我的案例类 C
是服务器的其中 A
和乙
将是在启动时加载的插件。这些居住在自己的文件夹。
However, my case is a bit more complicated. In my case class C
is a server where A
and B
will be plugins that are loaded on startup. These are residing in their own folder.
我也有一个名为类 Cfactory
。在Cfactory我有一个 __新__
方法,将创建一个功能齐全的对象C.在 __新__
方法,我的搜索的为插件,使用 __导入__
加载它们,然后将它们分配给ç.__ bases__ + =(loadedClassTypeGoesHere,)
I also have a Class named Cfactory
. In Cfactory I have a __new__
method that will create a fully functional object C. In the __new__
method I search for plugins, load them using __import__
, and then assign them to C.__bases__ += (loadedClassTypeGoesHere, )
所以,下面是一个可能性:(说得很抽象)
So the following is a possibility: (made it quite abstract)
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错误:
This again will not work, and will give the MRO errors again:
类型错误:无法创建一个一致的方法解析结果
顺序(MRO)为基础对象,
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, A
这是简单的办法解决这是从 A
和 B <删除
对象
基类/ code>。然而,这将使得当这些插件正在运行的独立哪些应避免它们的旧式对象(这应该是可能的,的UnitTest明智)
An easy fix for this is removing the object
baseclass from A
and B
. However this will make them old-style objects which should be avoided when these plugins are being run stand-alone (which should be possible, UnitTest wise)
另一个简单的办法是消除对象
从 C
但是这也将使得旧式类ç.__基地__
将不可用,因此,我不能额外的对象添加到 C
Another easy fix is removing object
from C
but this will also make it an old-style class and C.__bases__
will be unavailable thus I can't add extra objects to the base of C
什么将是一个很好的架构解决方案,你会怎么做这样的事?现在我可以用老式类的插件,自己居住。但我宁可不使用它们。
What would be a good architectural solution for this and how would you do something like this? For now I can live with old-style classes for the plugins themselves. But I rather not use them.
推荐答案
想想这样说 - 你想要的混入重写某些对象
的行为,所以他们需要的是中的方法解析顺序对象
之前。
Think of it this way -- you want the mixins to override some of the behaviors of object
, so they need to be before object
in the method resolution order.
所以,你需要改变基地的顺序:
So you need to change the order of the bases:
class C(A, B, object):
pass
由于这个bug ,需要 C
不继承直接目的是能够正确地分配给 __ __基地
,工厂确实可能只是一个功能:
Due to this bug, you need C
not to inherit from object directly to be able to correctly assign to __bases__
, and the factory really could just be a function:
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()
这篇关于如何动态地添加混入作为基类没有得到MRO错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!