Python 有没有一种方法可以获取带有非局部变量的dict对象?
我想知道,Python中是否有一个函数可以返回包含封闭函数中使用的非局部变量的dict对象?如Python 有没有一种方法可以获取带有非局部变量的dict对象?,python,python-3.x,Python,Python 3.x,我想知道,Python中是否有一个函数可以返回包含封闭函数中使用的非局部变量的dict对象?如vars()或locals()用于局部变量,或globals()用于全局变量 更新: 正如Bjorn所指出的,嵌套函数中实际使用的非局部变量包含在local列表中。关于3.2.3,以下代码 >>> def func1(): ... x=33 ... def func2(): ... # Without the next line prints {
vars()
或locals()
用于局部变量,或globals()
用于全局变量
更新:
正如Bjorn所指出的,嵌套函数中实际使用的非局部变量包含在local
列表中。关于3.2.3,以下代码
>>> def func1():
... x=33
... def func2():
... # Without the next line prints {}
... print(x)
... print(locals())
... func2()
...
>>> func1()
返回
{'x':33}
没有内置的非局部变量()
,但您可以自己创建一个:
def nonlocals():
import inspect
stack = inspect.stack()
if len(stack) < 3: return {}
f = stack[2][0]
res = {}
while f.f_back:
res.update({k:v for k,v in f.f_locals.items() if k not in res})
f = f.f_back
return res
def nonlocals():
进口检验
stack=inspect.stack()
if len(stack)<3:返回{}
f=堆栈[2][0]
res={}
当f.f_返回时:
res.update({k:v代表k,v在f.f_locals.items()中,如果k不在res})
f=f.f_后
返回res
如果我在你的程序上运行它,我会得到:
{'func2': <function func1.<locals>.func2 at 0x0000000002A03510>, 'x': 33}
{'func2':,'x':33}
公认的答案非常非常错误-f_back
给出的是调用方,而不是词法上的父范围
Python是词汇范围的,而不是动态范围的
可以使用所述方法完成所需操作:
快速测试表明,在Python 3.3中,
nonlocal
名称包含在locals
中,您使用的是什么版本?不,只有在本地使用时才包含在locals中…@delnan我使用的是3.2.3。在这个版本中,locals()
如果在嵌套函数中使用,则返回{}
。我怀疑您的测试有缺陷。locals()
只返回局部变量和自由变量。如果您的内部函数中有一个非本地函数(即您没有使用它),则locals()
不会列出它。谢谢您的回答!在IronPython中,如果没有命令行选项-X:FullFrames
,这将不起作用,因为这会影响性能,应该只用于调试。一般来说,Python的实现不必支持堆栈帧检查。不要使用它,这是非常错误的!!它使用动态范围而不是词汇范围查找变量!!嗯。。你不是在用上面的.f_back
吗(链接的答案没有这个功能)。@thebjorn:是的,很好。链接的答案不需要这样做,因为它的调用者已经调用了inspect.currentframe()
,并提供了它的起始堆栈帧,所以答案不需要这样做。但是,在这里,我没有提供起始帧
,因此我需要通过检查堆栈来获得它。这与变量查找机制完全不同。我在这里没有做的是使用.f\u back
链动态查找变量(请参阅接受答案中循环内的.f\u back
),这就是答案的问题。啊,我明白了。您是否也可以解决原始问题,即获取不在globals()
和locals()
中的所有词汇范围变量的dict?这意味着,从OPs代码返回{'x':33}
,而不需要通过使用变量(这里通过调用print)或使用非局部语句声明它来将变量拉入局部变量?@thebjorn:不幸的是,据我所知,这是不可能的,因为封闭函数不存储对其封闭函数的引用。它只直接存储对包含闭包变量的单元格的引用,这仅适用于闭包中的变量。事实上,如果变量不在闭包中,那么此时它们甚至可能不存在。(换句话说,这需要Python程序无限期地存储自己的执行历史记录,永远不要丢弃它,因为以后可能有人决定从某个死帧中查找变量。)
def nonlocals():
import inspect
caller = inspect.currentframe().f_back
return {k: v for k, v in caller.f_locals.items() if k in caller.f_code.co_freevars}