装饰器函数中返回wrapper的疑问:为何返回、返回至何处?
关于装饰器返回wrapper的疑问解答
嘿,这个问题问到点子上了——装饰器的返回逻辑确实是很多刚接触Python装饰器的同学会困惑的点,咱们结合你的代码一步步理清楚:
首先得搞懂@语法糖背后的本质
当你用@deco修饰ortalama函数时,Python在后台悄悄执行了这行代码:
ortalama = deco(ortalama)
也就是说,被装饰的函数名(这里是ortalama)会被重新赋值为装饰器函数(deco)的返回值。这是理解整个问题的核心!
为什么必须返回wrapper?返回的目的地是哪里?
- 返回的
wrapper其实就是替换掉了原来的ortalama函数。当你后面调用ortalama(liste)时,你实际调用的是deco返回的这个wrapper函数,而不是最开始定义的那个ortalama。 - 如果不返回
wrapper,比如你改成直接返回None或者其他值,那ortalama就不再是一个可调用的函数了——它会变成你返回的那个值,后面调用ortalama(liste)时就会报错,因为你不能像调用函数一样去调用一个普通值。
为什么不能在deco里直接调用wrapper()?
咱们来试一下把你的代码改成这样(直接调用wrapper而不是返回):
import time def deco(fun) : def wrapper(*args) : ba = time.time() giden = fun(*args) so = time.time() print(f"{so-ba} 秒过去了") return giden # 这里改成直接调用wrapper,而不是返回 wrapper() @deco def ortalama (liste): t = 0 for i in liste: t += i return t liste = list(range(0,10)) a = ortalama(liste) # 这里会报错! print(a)
运行这段代码你会发现:
- 脚本一启动,还没执行到
a = ortalama(liste),wrapper()就已经被执行了——因为@deco在定义ortalama的时候就会调用deco(ortalama),里面的wrapper()会立刻执行。 - 更严重的是,
deco函数没有返回值(默认返回None),所以ortalama被赋值成了None。当你后面尝试调用ortalama(liste)时,就会抛出TypeError: 'NoneType' object is not callable的错误。
简单来说,直接调用wrapper()的话,你是在装饰阶段就立刻执行了函数逻辑,而不是把增强后的函数逻辑保存下来,等到需要的时候再调用。这完全违背了装饰器的初衷——装饰器的作用是给函数“增强功能”,而不是“立刻执行函数”。
回到你的原代码,整个流程是怎样的?
- 定义
deco和wrapper函数。 - 用
@deco修饰ortalama,Python执行ortalama = deco(ortalama),此时deco接收的fun参数是原来的ortalama函数,然后返回wrapper函数,所以现在ortalama指向了wrapper。 - 当你调用
ortalama(liste)时,实际调用的是wrapper(liste):- 先记录开始时间
ba; - 调用
fun(*args),也就是调用原来的ortalama函数,计算列表总和; - 记录结束时间
so,打印耗时; - 返回原函数的结果
giden,所以a拿到的是列表的总和45。
- 先记录开始时间
这样就完美实现了“给原函数添加计时功能,但不修改原函数代码”的装饰器效果~
内容的提问来源于stack exchange,提问作者mahmut özer
相关产品推荐
相关产品推荐

