基于类的装饰者的合同

时间:2017-11-22 16:45:23

标签: python decorator

Answer谈论功能装饰的合同。

以下是基于类的装饰器的代码,

def hello_world(obj):
   return 'Hello World'

@hello_world
class C:
   pass

很明显,基于类的装饰器接受Class类型对象作为参数。要返回一个对象,

基于类的装饰者的合同是什么?

2 个答案:

答案 0 :(得分:3)

小心你的术语 - 当人们谈论“类装饰器”时,他们可能意味着“基于类的装饰器”,即它是用可调用类而不是函数实现的装饰器。

类装饰器和普通装饰器之间没有“契约”差异。可以说,没有“类装饰器”这样的东西 - 它只是一个恰好装饰类的装饰器。

MaterialComponents

以上内容与以下内容相同:

@dec
def foo():
    pass

@dec
class C:
    pass

当接收到的参数是函数对象与类对象时,完全取决于def foo(): pass foo = dec(foo) class C: pass C = dec(C) 的实现,这与装饰器模式本身无关。

在大多数用例中,函数上的装饰器应返回函数,类上的装饰器应该返回类,但语言中没有这样的限制。例如,函数上的装饰器可以返回可调用类的实例。

答案 1 :(得分:2)

在大多数情况下,隐含的期望是任何设计用作装饰器的函数或类都应该返回一个对象,其行为与提供的对象相同。但是,Python中没有任何内容强制执行此“合同”。

如果您的装饰器被赋予了一个类并返回一个字符串(如您的示例中所示),那么人们可能会感到困惑,因为字符串很可能与类的行为方式不同。在装饰类时,您可能希望避免删除实例/类/静态方法或类变量。您可能想要更改它们或添加新的,但通过使用装饰器来剥离类主体中定义的功能会很奇怪。这方面的一个例子如下所示:

class -> string

实质上,您的{{1}}示例违反了这种隐含的期望,因为我们无法再使用其正文中定义的类。借用鸭子打字命名法,有一些期望你的返回物体仍然像鸭子一样嘎嘎叫。同样,通常鼓励在编写Python时遵循Principle of Least Astonishment