我想提交一个我经常在我的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,但是对于已经有基类的复杂继承,解决方案可能并不明显。
什么是最好的设计模式?
答案 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}}。这是你的选择,无论你的代码结构更适合什么。