Python装饰器无法识别全局变量



我刚刚编码的问题的mwe:

from decorator import decorator

@decorator
def deco(func, deco_name=None, *args, **kwargs):
print(f"DECORATOR {deco_name} APPLIED")
return func(*args, **kwargs)

deco_name = None

class Greeter:
def __init__(self, _deco_name):
global deco_name
deco_name = _deco_name
@deco(deco_name=deco_name)
def hello(self, name):
print(f"Hello {name} :)")
print(deco_name)

g = Greeter("MYDECO")
g.hello("Yoshi")

控制台输出:

DECORATOR None APPLIED
Hello Yoshi :)
MYDECO

我在我的项目中也有类似的设置,我不明白为什么decorator函数deco((不知道全局变量deco_name的更新值的值(它打印的是decorator None APPLICED,而不是decorator MYDECO APPLICED(。修饰函数hello((确实知道更新值,正如上次print语句生成的MYDECO所看到的那样。我需要一些方法在运行时设置一个全局变量并将其传递给装饰器,如果有人能a(向我解释为什么我的方法是错误的,b(给我一个修复/替代解决方案,我会很高兴。

提前谢谢。

主要问题是在创建类时创建装饰器。因此,在设置变量之前会调用外部装饰器。您可以将所有这些放在包装器函数中,这样只有在调用hello()时才会调用它。

我不确定你为什么在这里使用全局变量。您可以访问包装器函数中的实例变量,这对我来说更有意义。下面是一个设置和访问全局变量和实例变量的示例。也许它会把事情指向一个有用的方向:

def deco(f):
def wrapper(*args):
instance = args[0]
print(f"DECORATOR Instance {instance.deco_name} APPLIED")
print(f"GLOBAL NAME {global_deco_name} APPLIED")
f(*args)
return wrapper
global_deco_name = "global_deco"
class Greeter:
def __init__(self, _deco_name):
global global_deco_name
self.deco_name = _deco_name
global_deco_name = _deco_name
@deco
def hello(self, name):
print(f"Hello {name} :)")
print(self.deco_name)
print(global_deco_name)


g = Greeter("MYDECO")
g.hello("Yoshi")

打印

DECORATOR Instance MYDECO APPLIED
GLOBAL NAME MYDECO APPLIED
Hello Yoshi :)
MYDECO
MYDECO

我很确定这里发生的事情是在对象初始化之前解释deco_name。当你在一个类中注释一个函数时,几乎会发生这样的情况,即装饰器是";准备好的";一旦类本身被解释,这意味着在您分配g.时@deco是不可更改的

最好的选择可能是将hello打包到一个不同的函数中,该函数可以实现装饰器的功能:

def hello(self, name):
return deco(self._hello, deco_name=self.deco_name, name)
def _hello(self, name):
# your hello

这还将用类属性替换全局deco_name。

最新更新