为什么被Python装饰器修饰的函数__name__属性返回wrapper而非原函数名?
原理说明
装饰器本质是Python的语法糖,你代码里的@logging_decorator写法等价于在a_function定义完成后,额外执行了一次赋值操作:
a_function = logging_decorator(a_function)
你定义的logging_decorator返回值是内部嵌套的wrapper函数,这就意味着原来指向原函数的a_function变量,最终会被替换为指向wrapper函数的引用。
当你在原函数内部执行print(f'This is the Function name {a_function.__name__}')时,代码查询的是当前作用域下a_function这个变量指向的函数的__name__属性,此时a_function已经是wrapper函数,自然会输出wrapper。
你代码里第一行打印This is {function.__name__}能输出原函数名,是因为function是装饰器被调用时传入的原函数引用,这个变量一直指向未被替换前的原函数对象。
另外你当前的写法里wrapper函数没有返回output变量,最终a_function(3,4,5)的返回值会是None,也需要对应调整。
修复方案
可以使用Python标准库functools提供的wraps装饰器,它会自动把原函数的元信息(包括__name__、文档字符串等)拷贝到装饰器的内层wrapper函数上,让装饰后的函数保留原函数的属性标识:
修复后的代码示例:
from functools import wraps def logging_decorator(function): @wraps(function) def wrapper(*args, **kwargs): print(f'This is {function.__name__}') output = function(*args, **kwargs) return output return wrapper @logging_decorator def a_function(a, b, c): print(f'This is the Function name {a_function.__name__}') return a * b * c res = a_function(3, 4, 5)
修改后打印的a_function.__name__就会是预期的a_function。
内容的提问来源于stack exchange,提问作者Paul Ged
相关产品推荐
相关产品推荐

