nin*_*cko 20
装饰...:
例如
@decoA
@decoB
@decoC
def myFunc(...): ...
...
Run Code Online (Sandbox Code Playgroud)
相当于:
def myFunc(...): ...
...
myFunc = decoA(decoB(decoC(myFunc))) #note the *ordering*
Run Code Online (Sandbox Code Playgroud)
多重继承...:
__init__
除非明确调用子类方法(通过方法解析顺序),否则不会调用子类方法协议)!总而言之,如果他们没有返回代理对象,我会使用装饰器进行类似mixin的行为.一些示例将包括任何返回原始函数的装饰器,稍微修改(或在某处注册或将其添加到某个集合之后).
你经常会找到装饰器的东西(比如memoization)也是很好的候选者,但如果他们返回代理对象,应该适度使用; 它们的应用顺序很重要.并且太多的装饰器在彼此之上以他们不打算使用的方式使用它们.
如果它是一个"经典继承问题",或者如果我对mixin行为所需要的只是方法,我会考虑使用继承.经典的继承问题是您可以在任何可以使用父级的地方使用子级的问题.
一般来说,我尝试编写代码,而不必增强任意内容.
其他答案都很好,但我想给出一个简洁的优缺点列表。
mixins 的主要优点是可以在运行时使用检查类型isinstance
,并且可以使用 MyPy 等 linter 进行检查。与所有继承一样,当存在is-a关系时应该使用它。例如,dataclass
可能应该是一个 mixin,以便公开特定于数据类的内省变量,例如数据类字段列表。
当您没有is-a关系时,应该首选装饰器。例如,从另一个类传播文档或在某个集合中注册类的装饰器。
装饰通常只影响它所装饰的类,而不影响从基类继承的类:
@decorator
class A:
... # Can be affected by the decorator.
class B(A):
... # Not affected by the decorator in most cases.
Run Code Online (Sandbox Code Playgroud)
既然 Python 有了__init_subclass__
,装饰器能做的一切都可以通过 mixins 来完成,而且它们通常会影响子子类:
class A(Mixin):
... # Is affected by Mixin.__init_subclass__.
class B(A):
... # Is affected by Mixin.__init_subclass__.
Run Code Online (Sandbox Code Playgroud)
Mixins还有另一个优点,那就是它们可以提供空的基类方法。子类可以用一些“增强”行为重写这些方法,然后调用 super. 装饰器不能轻易提供这样的基类方法。这是 mixin 更加灵活的另一种方式。
总之,在决定 mixin 和装饰时应该问的问题是:
isinstance
?一般来说,倾向于继承。
您引用的问题不是在装饰器和类之间做出决定。它使用装饰器,但您可以选择使用:
装饰器只是“包装”模式的一个奇特名称,即用其他东西替换某些东西。实现取决于您(类或函数)。
在它们之间做出决定时,这完全取决于个人喜好。你可以与另一个人一起做你能做的一切。
(为什么这是一个好主意?可能会假设修饰函数仍然是函数,修饰类仍然是类。)
在这两种情况下,更好的是使用一个装饰器,它只返回原始的,并以某种方式修改。
编辑:在更好地理解你的问题之后,我在 Python functools.wraps 上发布了另一个解决方案,相当于类
归档时间: |
|
查看次数: |
4270 次 |
最近记录: |