Python中的装饰器语法与要装饰的装饰器和函数具有相同的名称

问题描述 投票:0回答:1

当装饰器和要装饰的函数同名时,Python 中的装饰器语法如何工作?请参阅下面的代码

def say_hello(func):
    def wrapper(x):
        return x.upper()
    return wrapper

@say_hello
def say_hello(string):
    return string

say_hello('hello')

这里装饰器的名称和要装饰的函数的名称是相同的..代码工作正常并将返回装饰输出“HELLO”。

我不明白的是,当定义第二个“say_hello”函数(要装饰的函数)时,为什么它不立即覆盖全局命名空间中的第一个“say_hello”函数(装饰器)?程序如何仍然可以访问第一个“say hello”函数?装饰器语法是否有自己的命名空间,并且第二个“say_hello”函数仅在此命名空间中定义,而不是全局定义?

python-decorators
1个回答
0
投票

这是因为当在函数定义上声明装饰器时,直到使用新函数对象调用装饰器并返回最终函数对象时,才会分配函数名称。

摘自PEP-318

Python 中实现的函数装饰器的当前语法 2.4a2 是:

@dec2
@dec1
def func(arg1, arg2, ...):
    pass

这相当于:

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))

无需对变量进行中间赋值

func

请注意“没有对变量

func
进行中间赋值”的部分。因此,在您的情况下,新函数对象没有中间变量名称
say_hello
。新的函数对象首先传递给装饰器
say_hello
,装饰器返回最终的函数对象,然后将其分配给名称
say_hello
(并覆盖引用装饰器的原始
say_hello
名称)。

另请注意,您可能应该制作包装函数

return func(x.upper())
,而不是使其成为
func
的实际包装。

© www.soinside.com 2019 - 2024. All rights reserved.