首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python修饰器无法识别全局变量

Python修饰器无法识别全局变量
EN

Stack Overflow用户
提问于 2021-05-06 22:39:08
回答 2查看 185关注 0票数 0

我刚刚编码的问题的mwe:

代码语言:javascript
复制
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")

控制台输出:

代码语言:javascript
复制
DECORATOR None APPLIED
Hello Yoshi :)
MYDECO

我在我的项目中有一个类似的设置,我不能理解为什么装饰器函数deco()不知道全局变量deco_name的更新值(它输出装饰器None APPLIED而不是装饰器MYDECO应用)。修饰函数hello()确实知道由最后一条print语句生成的MYDECO所看到的更新值。我需要一些方法来设置运行时的全局变量,并将其传递给装饰器,如果有人能a)向我解释为什么我的方法是错误的,b)给我一个修复/替代解决方案,我会很高兴的。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-06 23:03:53

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

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

代码语言:javascript
复制
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")

打印

代码语言:javascript
复制
DECORATOR Instance MYDECO APPLIED
GLOBAL NAME MYDECO APPLIED
Hello Yoshi :)
MYDECO
MYDECO
票数 2
EN

Stack Overflow用户

发布于 2021-05-06 22:51:38

我非常确定这里发生的事情是deco_name在对象初始化之前被解释。当你在一个类中注释一个函数时所发生的事情是,一旦类本身被解释,装饰器就是“准备好的”,这意味着@deco在你赋值g的时候是不可改变的。

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

代码语言:javascript
复制
def hello(self, name):
  return deco(self._hello, deco_name=self.deco_name, name)
def _hello(self, name):
  # your hello

这也会将全局deco_name替换为类属性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67420365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档