合同:函数将函数作为参数并返回函数[即已修改(或相同)版本的函数]。例如,通过函数,这里是square
。装修工合同
@floatify
def square(n):
return n*n
是装饰者是否只返回传递函数的装饰版本,但没有别的?
合同:函数将函数作为参数并返回函数[即已修改(或相同)版本的函数]。例如,通过函数,这里是square
。装修工合同
@floatify
def square(n):
return n*n
是装饰者是否只返回传递函数的装饰版本,但没有别的?
它应该只返回一个函数,但没有阻止你返回任何你想要的东西。
>>> def d(x):
... return "hello"
...
>>> @d
... def f():
... return "world"
...
>>> f
'hello'
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
>>>
我不明白,但我喜欢。我需要阅读装饰器... – ratskin
@ratskin包括上面的装饰器的功能是一样的后面添加'function = decorator(function)'。 –
没有任何东西阻止我返回任何东西,这是一种错误运用装饰者思想的简单方法。可能你应该删除那个短语,在你的答案 – overexchange
装饰函数应该返回一个函数,因为它返回的任何东西都会被绑定到原始函数的名字上。所以如果返回的对象不是一个函数(或者其他一些可调用的,比如一个类的构造函数或者可调用的类实例),那就相当混乱。
通常返回的函数应该有一个与原始函数兼容的函数签名,但我想如果返回的函数也需要额外的参数,那也没关系。另外,返回函数的返回类型应该与原始函数的返回类型兼容。
装饰函数有点像原始函数的子类,所以遵循Liskov substitution principle是有意义的。
装饰功能可能有副作用:例如,它可以修改一些全局。这可能是有用的,例如用于记录目的; OTOH,功能通常应避免有副作用。
FWIW,一些标准函数装饰器返回非函数可调参数,最常见的可能是@classmethod
。
装饰者没有什么特别的神奇。由于贾里德Goguen在评论中提到,
@decorator
def some_function(args):
#etc
是相同的
def some_function(args):
#etc
some_function = decorator(some_function)
第二种形式是长一点,但功能更强大,因为你可以选择返回的功能结合到一个不同的名称, 如果你想。如果不是完全不可能使用@
语法,那么使用较长语法可以轻松完成的一些事情可能很困难。
[这里](https://stackoverflow.com/a/34558606/2482744)是一个装饰器的例子,它以非常有用的方式返回非函数。 –
@Alex ???那些是功能......我错过了什么? –
@JaredGoguen lambdas是实际的装饰器,而'skip [除了]'是产生装饰器的函数。所以装饰的功能可以替换为None。 –
装饰可以作为
代码在您的查询是功能装饰,即取代装饰福(square
)与wrapper
。wrapper
执行以下操作:
f(n)
float
到result
并返回。def floatify(f):
def wrapper(n):
result = f(n)
return float(result)
return wrapper
功能装饰的合同:
的替换功能通常荣誉的装饰功能的合同:
的替换功能应该从装饰功能
@functools.wraps(f)
最常见的情况是返回一个新的函数(一个包装器),它使用传递函数,它不是传递函数的修改版本。 –
@AlexHall修改过的函数我的意思是,无论如何,这个函数使用传递的函数。 – overexchange
好的,我只是想澄清一下,因为有时装饰器可能会简单地设置传入函数的属性,然后将其返回,这是我认为您的修改版本的含义。 –