我正在开发一个python项目,我需要使用大约20个不同的类来实现一系列功能,例如:“download”,“parse”,“update”等。
使用超类可以很容易地分解几个功能,因为所有代码对于所有代码都是相同的。
但有时候,特别是对于“解析”方法,我有10个必须实现相同算法的类和10个需要特定算法的类。
基于我对python的了解,使用mixins可以很容易地分解这种行为。
但即使“解析”算法相同,这里也存在问题,我需要将标记应用于解析的条目,并且此标记特定于每个类。我想知道这是否是一种使用class属性的正确方法,该属性仅由mixin用于实现此目标。
这段代码给出了如何使用属性的示例:
class MyMixin():
def parse(self):
print(self.tag)
...
class MyClass(MyMixin):
tag = 'mytag'
我已经在一些框架(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()
或那:
class MyMixin():
def do_something(self, tag):
print(tag)
class MyClass(MyMixin):
tag = 'mytag'
if __name__ == '__main__':
c = MyClass()
c.do_something(c.tag)
答案 0 :(得分:1)
在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()
(Python 3的代码可能略有不同)
这样就可以很好地及早地捕获错误,而不是在访问属性时捕获错误。
此外,PyCharm警告该类在定义中不完整。其他静态分析工具也可能会选择它。
答案 1 :(得分:1)
您可以使用mixins在其他类中实现合成。这样,您可以将功能委托给mixin并在其他类中重用mixin。因此,使用python时,您对混合模块有两个规则:
这两个规则将继承设置为继承。
因此,要回答您的问题,是的,如果您确定父级具有这些属性,则可以使用父级属性。
一个小例子(来自: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.
django restframework示例也非常好:django rest framework mixins