我想提交一个我在工作中经常看到的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。
在这种平凡的情况下,用中间类替换mixin是可能的,但在已经有基类的复杂继承情况下,解决方案可能不明显。
你认为最好的设计模式是什么?
嗯,正如我在评论中指出的,这就是Python的工作方式,我不认为改变它是一个好主意。
然而,元类可以拯救我们!
您可以创建自己的元类,并使其尽可能复杂。这里我将向您展示一个非常基本的示例。
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中。这是你的选择,任何适合你的代码结构。