Python decorator 装饰器的 wrapper 问题
问题:
def log(func):
def wrapper(*args, **kwargs):
print('before call %s' % func.__name__)
func(*args, **kwargs)
print('after call %s' % func.__name__)
return wrapper
@log
def test_func(a, b):
print('%d + %d = %d' % (a, b, a + b))
使用 @log
的 decorator 后,以下的打印会跟预期的不一致,并不是预期的 test_func
,而变成了 wrapper
:
>>> print('name: %s' % (test_func.__name__))
name: wrapper
原因:
之所以会这样,是因为在使用 decorator 后,test_func
变成了 log(test_func)
的返回,即 wrapper
函数。
解决:
标准库提供了 functools.wraps
这样的 decorator,可以这样使用来装饰上述 wrapper 函数:
def log(func):
+ @functools.wraps(func)
def wrapper(*args, **kwargs):
print('before call %s' % func.__name__)
func(*args, **kwargs)
print('after call %s' % func.__name__)
return wrapper
@log
def test_func(a, b):
print('%d + %d = %d' % (a, b, a + b))
>>> print('name: %s' % (test_func.__name__))
name: test_func
这样就跟预期的结果一致了。