[英]what is difference between foo=bar(foo) and something=bar(foo) in decorator in python?
I read about we can create reference of any function in python but i also read that while creating a decorator we use a special syntax called "@" : ex: @decorator_function and this @decorator_function
is equal to new_function=decorator_function(new_function)
我读到我们可以在python中创建任何函数的引用,但同时我也读到在创建装饰器时,我们使用一种特殊的语法,称为“ @”:例如:@decorator_function,此
@decorator_function
等于new_function=decorator_function(new_function)
so my doubt is in my view both : 所以我都怀疑:
anything = decorator_function(new_function)
new_function=decorator_function(new_function)
both are playing the role of closure but both result different output. 两者都扮演着封闭的角色,但是两者都导致了不同的输出。 so what is big difference between both of them?
那么两者之间的最大区别是什么?
example code : 示例代码:
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)
The original something
function you wrote makes a recursive call to something
, not a
. 您编写的原始的
something
函数递归调用something
,而不是a
。
If you assign deco(something)
to a
, then something
is still the original function, and the recursive call will call the original function: 如果分配
deco(something)
到a
,然后something
仍然是原来的功能,以及递归调用将调用原始的功能:
something
, finds original function something
,找到原始功能 If you assign deco(something)
to something
, then something
is now the new function, and the recursive call will call the new function: 如果将
deco(something)
分配给something
,则something
现在是新函数,并且递归调用将调用新函数:
something
, finds new function something
,找到新功能 For the first one, a = deco(something)
对于第一个,
a = deco(something)
def deco(fn):
def wrapper(*args):
print('called')
return something(*args) # Notice here
return wrapper
The second one, something = deco(something)
is just the same except your original function something
now has become the wrapper
function that deco
returned. 第二个,
something = deco(something)
就是除了你的原始功能相同something
,现在已经成为wrapper
该功能deco
返回。
>>> something
<function deco.<locals>.wrapper at 0x7fbae4622f28>
>>> a
<function deco.<locals>.wrapper at 0x7fbae4622ea0>
Both something
and a
wrap the original something
before it was overridden by something = deco(something)
assignment. 这两个
something
和a
原包装something
之前,它是由覆盖something = deco(something)
分配。 Python internally stored the original something
function somewhere in the wrapper functions: Python内部将原始的
something
函数存储在包装函数中的某个位置:
>>> something.__closure__[0].cell_contents
<function something at 0x7fbae4622bf8>
>>> a.__closure__[0].cell_contents
<function something at 0x7fbae4622bf8>
In the last assignment something
has become something different: 在上一次作业中,
something
变得与众不同:
>>> something
<function deco.<locals>.wrapper at 0x7fbae4622f28>
Both of your assignments using manual calls to the decorator work. 您使用手动调用装饰器的两个工作。 But one of them (the one that rebinds
something
) replaces the original function so that it can't be reached by its original name any more. 但是其中之一(重新绑定
something
)替换了原来的函数,因此不再可以通过其原始名称来访问它。 It's not any different than using any other assignment. 与使用任何其他分配没有什么不同。 For instance:
例如:
def foo(x):
return x + 1
a = 10
a = foo(a)
When you assign the result of foo(a)
to a
, it replaces the old value of 10
with a new value 11
. 将
foo(a)
的结果分配给a
,它将旧值10
替换为新值11
。 You can't get the 10
any more. 您再也无法获得
10
了。
Decorator syntax does the same thing. 装饰器语法执行相同的操作。
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
It's not forbidden to use a decorator to create a differently named function, it's just not normally as useful (and so there's no special syntax for it): 禁止使用装饰器创建一个命名不同的函数,通常它没有那么有用(因此没有特殊的语法):
def func_3(x):
pass
func_4 = deco(func_3) # this works, creating a new function name without hiding the old one
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.