Answer谈论功能装饰的合同。
以下是基于类的装饰器的代码,
def hello_world(obj):
return 'Hello World'
@hello_world
class C:
pass
很明显,基于类的装饰器接受Class
类型对象作为参数。要返回一个对象,
基于类的装饰者的合同是什么?
答案 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。