我读到我们可以在python中创建任何函数的引用,但我也读到了在创建装饰器时我们使用了一种称为" @"的特殊语法。 :例如:@decorator_function
此@decorator_function
等于new_function=decorator_function(new_function)
所以我怀疑在我看来:
anything = decorator_function(new_function)
new_function=decorator_function(new_function)
两者都扮演着封闭的角色,但两者都产生了不同的输出。那么两者之间有什么大不同?
示例代码:
def deco(fn):
def wrapper(*args):
print('called')
return fn(*args)
return wrapper
def something(x):
if x == 0:
print('first')
something(x+1)
else:
print('hello')
print('new name')
a = deco(something)
a(0)
print('\nreassigning to the same name')
something = deco(something)
something(0)
答案 0 :(得分:4)
您编写的原始something
函数会对something
进行递归调用,而不是a
。
如果您将deco(something)
分配给a
,则something
仍然是原始函数,递归调用将调用原始函数:
something
,找到原始函数如果您将deco(something)
分配给something
,则something
现在是新功能,递归调用将调用新功能:
something
,找到新函数答案 1 :(得分:1)
对于第一个,run
a = deco(something)
第二个def deco(fn):
def wrapper(*args):
print('called')
return something(*args) # Notice here
return wrapper
与相同除了您的原始函数something = deco(something)
现在已成为something
返回的wrapper
函数。
deco
>>> something
<function deco.<locals>.wrapper at 0x7fbae4622f28>
>>> a
<function deco.<locals>.wrapper at 0x7fbae4622ea0>
和something
在a
分配覆盖原始 something
之前将其包裹起来。 Python在内部将原始something = deco(something)
函数存储在包装函数中的某个位置:
something
在最后一次作业中,>>> something.__closure__[0].cell_contents
<function something at 0x7fbae4622bf8>
>>> a.__closure__[0].cell_contents
<function something at 0x7fbae4622bf8>
变得与众不同:
something
答案 2 :(得分:0)
使用手动调用装饰器的两个作业都有效。但是其中一个(重新绑定something
)替换了原始函数,因此无法再通过其原始名称来访问它。它与使用任何其他任务没有任何不同。例如:
def foo(x):
return x + 1
a = 10
a = foo(a)
当您将foo(a)
的结果分配给a
时,它会将10
的旧值替换为新值11
。您无法再获得10
。
装饰器语法做同样的事情。
def deco(fn):
def wrapper(*args):
print('called')
return fn(*args)
return wrapper
def func_1(x):
pass
func_1 = deco(func_1) # replace the old func_1 with a decorated version
@deco # the @ syntax does the same thing!
def func_2(x):
pass
不禁止使用装饰器来创建不同名称的函数,它通常不常用(因此没有特殊的语法):
def func_3(x):
pass
func_4 = deco(func_3) # this works, creating a new function name without hiding the old one