J1b*_*1bz 7 python design-patterns mixins
我正在开发一个 python 项目,我需要使用大约 20 个不同的类来实现一系列功能,例如:“下载”、“解析”、“更新”等。
使用超类可以轻松分解多个功能,因为所有功能所需的代码都相同。
但有时,特别是对于“解析”方法,我有 10 个类必须实现相同的算法,而另外 10 个类需要特定算法。
根据我对 python 的了解,这种行为可以通过使用 mixin 轻松分解。
但是即使“解析”算法相同,这里也存在问题,我需要将标签应用于解析的条目,并且该标签特定于每个类。我想知道这是否是使用仅由 mixin 使用的类属性来实现此目标的正确方法。
这段代码给出了如何使用属性的示例:
class MyMixin():
def parse(self):
print(self.tag)
...
class MyClass(MyMixin):
tag = 'mytag'
Run Code Online (Sandbox Code Playgroud)
我已经在一些框架(http://www.django-rest-framework.org/api-guide/generic-views/)中看到了它,但我很想知道社区的意见。
==========================
编辑
用一个具体的例子来总结一下,我应该这样写:
class MyMixin():
def do_something(self):
print(self.tag)
class MyClass(MyMixin):
tag = 'mytag'
if __name__ == '__main__':
c = MyClass()
c.do_something()
Run Code Online (Sandbox Code Playgroud)
或者那个 :
class MyMixin():
def do_something(self, tag):
print(tag)
class MyClass(MyMixin):
tag = 'mytag'
if __name__ == '__main__':
c = MyClass()
c.do_something(c.tag)
Run Code Online (Sandbox Code Playgroud)
小智 8
您可以使用 mixins 在其他类中实现组合。通过这种方式,您可以将功能委托给 mixin 并在其他类中重用 mixin。因此,在使用 python 时,你对 mixin 有两个规则:
这两条规则将 mixin 与继承区分开来。
所以要回答你的问题,是的,你可以使用父属性,如果你确保父属性具有这些属性。
一个小例子(来自:https : //mail.python.org/pipermail/tutor/2008-May/062005.html):
class Base(object):
"""Base class for mixer classes. All mixin classes
require the classes they are mixed in with to be
instances of this class (or a subclass)."""
def __init__(self,b):
self.b = b # Mixin classes assume this attribute will be present
class MixinBPlusOne(object):
"""A mixin class that implements the print_b_plus_one
method."""
def __init__(self):
print 'MixinBPlusOne initialising'
def print_b_plus_one(self):
print self.b+1
class MixinBMinusOne(object):
"""A mixin class that implements the print_b_minus_one
method."""
def __init__(self):
print 'MixinBMinusOne initialising'
def print_b_minus_one(self):
print self.b-1
class Mixer(Base,MixinBPlusOne,MixinBMinusOne):
"""A mixer class (class that inherits some mixins), this
will work because it also inherits Base, which the
mixins expect."""
def __init__(self,b):
# I feel like I should be using super here because
# I'm using new-style classes and multiple
# inheritance, but the argument list of
# Base.__init__ differs from those of the Mixin
# classes, and this seems to work anyway.
Base.__init__(self,b)
MixinBPlusOne.__init__(self)
MixinBMinusOne.__init__(self)
class BrokenMixer(MixinBPlusOne,MixinBMinusOne):
"""This will not work because it does not inherit Base,
which the mixins expect it to do."""
pass
m = Mixer(9)
m.print_b_plus_one()
m.print_b_minus_one()
m = BrokenMixer(9)
m.print_b_plus_one() # It'll crash here.
Run Code Online (Sandbox Code Playgroud)
django restframework 示例也非常好:django rest framework mixins
您可以借助该abc模块获得一些额外的安全性:
from abc import abstractproperty, ABCMeta
class Parser(object):
__metaclass__ = ABCMeta
@abstractproperty
def tag(self):
pass
class Concrete(Parser):
@property
def tag(self):
return 'concrete'
print Concrete().tag # => prints 'concrete'
class Incomplete(Parser):
pass
# Raises error:
# TypeError: Can't instantiate abstract class Incomplete with abstract methods tag
Incomplete()
Run Code Online (Sandbox Code Playgroud)
(Python 3 的代码可能略有不同)
这样,错误就可以尽早被捕获,而不是在访问属性时捕获。
此外,PyCharm 会警告该类的定义不完整。其他静态分析工具可能也可以解决这个问题。