Python中装饰器与被装饰函数同名时的语法运行机制问询
装饰器与被装饰函数同名的执行逻辑解析
先看你给出的代码:
def say_hello(func): def wrapper(x): return x.upper() return wrapper @say_hello def say_hello(string): return string say_hello('hello')
核心原因:装饰器语法的执行顺序
Python的@装饰器名语法是个语法糖,它的执行逻辑是按步骤来的,根本不会出现“被装饰函数刚定义就覆盖装饰器”的情况:
- 先完整定义被装饰的函数(也就是第二个
say_hello),此时这个函数只是临时存在,还没替换全局命名空间里的say_hello。 - 紧接着调用当前全局里的装饰器函数(第一个
say_hello),把刚定义的被装饰函数作为参数传进去。 - 最后把装饰器返回的结果(也就是
wrapper函数)重新赋值给全局的say_hello,这时候才完成对原装饰器的覆盖。
具体步骤拆解
- 第一步:执行第一个
def say_hello(func),全局命名空间里存入了这个装饰器函数。 - 第二步:遇到
@say_hello,Python先执行下面的def say_hello(string),生成被装饰的函数对象,但这时候它还没覆盖全局的say_hello。 - 第三步:调用全局的
say_hello(装饰器),把刚生成的被装饰函数传进去,得到wrapper函数。 - 第四步:把
wrapper赋值给全局的say_hello,这时候原装饰器才被替换掉。
关于命名空间的疑问
装饰器语法没有独立的命名空间,整个过程都在全局命名空间里完成。关键就是被装饰函数的定义和全局变量的覆盖是两个分开的动作:先定义函数(此时全局say_hello还是装饰器),用装饰器处理它,最后才把处理后的结果覆盖全局变量。
所以程序执行装饰器逻辑时,能正常访问到第一个say_hello,因为这时候第二个say_hello还没完成对全局变量的覆盖。
内容的提问来源于stack exchange,提问作者ddc
相关产品推荐
相关产品推荐

