python中的抽象方法和mixin

时间:2013-06-05 17:26:35

标签: python oop inheritance mixins language-concepts

我想提交一个我经常在我的python代码中看到的代码模式,在这里工作,我不满意它,我想要一个更好的解决方案。

以下是我们今天所拥有的:

class AbstractClass(object):
    ....
    def method1(self,...)
       raise NotImplementedError
    ...

class FirstImplementationMixin(object)
    def method1(self,....) 
       ...

class SecondImplementationMixin(object)
    def method1(self...)
       ....

class InstanciatedClass1(FirstImplementationMixin, AbstractClass)
    ....

class InstanciatedClass2(SecondImplementationMixin, AbstractClass)
    ....

你看到了诀窍吗?我必须在列表的第一个位置添加mixin 继承,我不喜欢这个解决方案。如果我们在第二个位置添加它,解释器将使用AbstractClass.method1,因此引发异常。

在这种微不足道的情况下,可以用中间类替换mixin,但是对于已经有基类的复杂继承,解决方案可能并不明显。

什么是最好的设计模式?

1 个答案:

答案 0 :(得分:0)

好吧,正如我在评论中指出的那样,这就是Python的工作原理,我不认为改变它是一个好主意。

然而,metaclasses救援!
您可以创建自己的元类,并根据需要使其变得复杂。在这里,我将向您展示一个非常基本的例子。

def mixed(name, bases, dct):
    return type(name, bases[1:] + (bases[0],), dct)

它只是将第一个基类移动到最后,所以现在先将实际的基类放在第一个,然后是所有的mixin。这意味着您只能使用一个基类。您可以通过某种约定来解除此限制,例如,您将首先列出基类,然后是None,然后是mixins;并且您的元类将查找此None并相应地重新排序元组。

class MixinA:
    pass

class MixinB:
    pass

class Base(object):
    pass

class Test(Base, MixinA, MixinB):
    __metaclass__ = mixed
>>> Test.__mro__
                 >
(<class '__main__.Test'>,
 <class __main__.MixinA at 0x6f8850db48>,
 <class __main__.MixinB at 0x6f8850dae0>,
 <class '__main__.Base'>,
 <type 'object'>)

当然,由于用于选择元类的规则,每次都不会指定__metaclass__。您可能会在模块级别设置__metaclass__,或者可能在您的mixins中设置{{1}}。这是你的选择,无论你的代码结构更适合什么。