You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python装饰器工作原理疑问:为何未出现预期的无限循环?

为什么你的代码没有触发无限循环?先搞懂装饰器的本质

哈哈,这个问题刚好戳中了装饰器最核心的逻辑——你误解了装饰器执行后函数的指向变化!咱们一步步拆解你的代码,就能明白为啥没出现无限循环了。

第一步:装饰器的“偷偷替换”动作

当你在salut()函数上方加@deco的时候,Python在代码运行阶段会自动执行一个隐藏操作:

salut = deco(salut)

划重点:你最初写的那个salut函数(就是打印"salut"的那个),被当成参数传给了deco;而deco返回的coucou函数,会直接覆盖掉原来的salut变量!

现在全局作用域里的salut,已经不是你最初定义的那个函数了——它现在指向的是coucou。而原来的那个原始salut,被保存在coucou的闭包中,也就是deco函数里的f参数,这个f会一直指向未被装饰的原始salut。

第二步:执行hi()的完整流程

当你调用hi()时,它会执行return salut()——这里的salut已经是被替换后的coucou了,所以完整流程是:

  1. 进入coucou(),先打印"this is function{}".format(f)(这里的f是原始的salut函数对象)
  2. 然后执行return f()——注意!这里调用的是闭包里的f,也就是原始的、未被装饰的salut,它只会打印"salut",不会再触发装饰器逻辑,自然不会无限循环。

什么时候才会触发无限循环?

如果你的coucou函数里写的是调用salut()而不是f(),那才会陷入无限循环:

def deco(f):
    def coucou():
        print("this is function{}".format(f))
        return salut()  # 这里调用的是已经被替换成coucou的salut
    return coucou

这时候,coucou里调用salut()其实就是调用它自己,会反复触发coucou的执行,直到栈溢出报错。

装饰器的核心总结

  • 装饰器本质是函数替换:用装饰器返回的新函数,直接替换掉原来的被装饰函数
  • 闭包保存原始函数:装饰器内部的新函数(比如coucou)通过闭包持有原始函数的引用,这样才能在不循环的前提下调用原始逻辑
  • 装饰器的核心价值:在不修改原始函数代码的前提下,给它增加额外功能(比如日志、计时、权限校验等)

内容的提问来源于stack exchange,提问作者Newgate Ace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:02:21