python - 如何在不出现 MRO 错误的情况下动态添加 mixin 作为基类?

标签 python class architecture method-resolution-order

假设我有一个类 A , BC .

AB都是 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是一个服务器,其中 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()

这将再次不起作用,并且会再次给出 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/

相关文章:

c++ - 从 QGraphicsItem Qt C++ 获取实际对象

architecture - 如何导致用户进程的 TLB 抖动?

architecture - 通用 View 与多个专业 View

python - 每个工作日在两个日期之间出现的次数

python - 加入整数列表

python - Virtualenv pip ssl - 尝试安装任何软件包时失败。错误: "ssl module in Python is not available"

c# - 设计具有可以使用附加属性扩展的实体的应用程序的最佳方法是什么?

Python 模拟具有不同结果的多个调用

php - 类型提示和默认参数值也是方法签名吗?

class - 如果我有实例列表,调用类函数的 Pythonic 方式