如何动态地添加混入作为基类没有得到MRO错误? [英] How do I dynamically add mixins as base classes without getting MRO errors?

查看:162
本文介绍了如何动态地添加混入作为基类没有得到MRO错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个类 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆