装饰者functools.wraps
调用方法functools.update_wrapper
。
我想了解使用wrap
代替update_wrapper
的必要性。
为什么我们不能使用update_wrapper
作为装饰器而不是使用wraps
?
例如:
from functools import update_wrapper
def wrap1(func):
def call_it(*args, **kwargs):
"""wrap func: call_it1"""
print('before call in call_it1')
return func(*args, **kwargs)
return update_wrapper(call_it, func)
@wrap1
def hello1():
"""test hello 1"""
print('hello world1')
hello1()
和
def wrap3(func):
@wraps(func)
def call_it(*args, **kwargs):
"""wrap func: call_it3"""
print('before call in call_it3')
return func(*args, **kwargs)
return call_it
@wrap3
def hello3():
"""test hello 3"""
print('hello world3')
hello3()
的工作。但为什么以下不是?
def wrap2(func):
@update_wrapper(wrapped=func) # error, see below
def call_it(*args, **kwargs):
"""wrap func: call_it2"""
print('before call in call_it2')
return func(*args, **kwargs)
return call_it
@wrap2
def hello2():
"""test hello 2"""
print('hello world2')
hello2()
有错误
TypeError: update_wrapper() missing 1 required positional argument: 'wrapper'
The declarations of wraps
and update_wrapper
是:
@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
和
functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
位置参数wrapper
是update_wrapper
的第一个参数,
那么为什么以下内容不会call_it
为wrapper
update_wrapper
提取{?1}}?
@update_wrapper(wrapped=func)
def call_it(*args, **kwargs):
有没有办法将update_wrapper
用作装饰器而不是wraps
?
答案 0 :(得分:1)
使用@
作为装饰器基本上归结为:
@(value)
def f(...):
...
与以下相同:
def f(...):
...
f = (value)(f)
现在,如果我们将它应用于您的案例:
@update_wrapper(wrapped=func)
def call_it(*args, **kwargs):
...
def call_it(*args, **kwargs):
...
call_it = update_wrapper(wrapped=func)(call_it)
这里的问题是第一次,它只用第二个参数调用。然后它立即引发错误。
这是因为update_wrapper
并非设计用作装饰器,但wraps
是装饰器(工厂)。