[免责声明:可能有更符合Python习惯的做法,但是我想知道Python中这里变量作用域如何工作]
我试图找到一种方法来创建一个装饰器,类似于将一个名称注入到另一个函数的作用域中(使该名称不会泄漏到装饰器作用域之外)。例如,如果我有一个函数,要求打印一个名为var
的变量,但它尚未被定义,我希望在调用该函数时在装饰器内定义它。以下是一个无法正常运行的示例:
c = 'Message'
def decorator_factory(value):
def msg_decorator(f):
def inner_dec(*args, **kwargs):
var = value
res = f(*args, **kwargs)
return res
return inner_dec
return msg_decorator
@decorator_factory(c)
def msg_printer():
print var
msg_printer()
我希望它打印出 "Message
",但实际上它给出了:
NameError: global name 'var' is not defined
回溯甚至指向了变量 var
的定义位置:
<ipython-input-25-34b84bee70dc> in inner_dec(*args, **kwargs)
8 def inner_dec(*args, **kwargs):
9 var = value
---> 10 res = f(*args, **kwargs)
11 return res
12 return inner_dec
所以我不明白为什么它找不到var
。
有没有办法做类似这样的事情?
def msg_printer(): print var
并尝试调用msg_printer
,我会得到相同的名称错误,但是如果我定义var='Hi'
然后调用它,它就可以正常打印。在这个例子中,var
在msg_printer
编译之后的运行时没有被定义吗? - beardcvar
,因此在编译时,var
被标记为全局名称。但是,如果存在父级作用域,则在编译时,var
将被标记为作用域名称,此时装饰器技巧也将不再起作用。 - Martijn Pietersvars(sys.modules[f.__module__]) is f.__globals__
(通常,一些项目会替换__module__
引用,例如SQLalchemy,它使用元编程来帮助文档编写)。 - Martijn Pieters