获取当前范围内所有变量及其值的字典

时间:2009-06-25 00:37:23

标签: python

请考虑以下代码段:

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(**VARS_IN_SCOPE)

myfunc(123)

其中VARS_IN_SCOPE是我之后的字典,其中包含globalVarparamVarlocalVar等。

我希望基本上能够引用字符串中当前范围内的所有变量。因此,预期的产出将是:

Vars: 25, 123, 30

我可以将**dict(globals().items() + locals().items())传递给format()来实现这一目标。这总是正确的还是这个表达式会错误处理的一些极端情况?

重写以澄清问题。

6 个答案:

答案 0 :(得分:34)

当你正在做的时候合并两个dicts的最佳方法(本地人重写全局变量)是dict(globals(), **locals())

缺少合并全局变量和局部变量的方法是(a)内置函数(我想这是故意的,即你不认为内置函数是“变量”......但是,它们可能是,如果你这样选择的话! - ),和(b)如果你在嵌套函数中,任何本地包含函数的变量(没有真正好的方法来获取所有那些,plus - 只有在嵌套函数中显式访问的那些,即“自由变量”,无论如何都会以闭包中的单元格的形式存活。)

我认为这些问题对你的预期用途没什么大不了的,但你确实提到了“极端情况”;-)。如果你需要覆盖它们,有很多方法可以获得内置函数(这很容易)和(不那么容易)所有单元格(在嵌套函数中明确提到的封闭函数的变量 - thefunction.func_code.co_freevars到获取名称thefunction.func_closure以获取单元格,cell_contents在每个单元格上获取其值。 (但是,请记住,这些只是来自嵌套函数代码中显式访问的函数的变量!)。

答案 1 :(得分:8)

这是否符合您的意图?

d = dict(globals())
d.update(locals())

如果我正确阅读了文档,您可以创建globals() dict的副本,然后覆盖任何重复项locals() dict插入新条目(因为无论如何,locals()应该在你的范围内有偏好。)


我没有任何运气获得正确的函数来返回调用函数范围内的完整变量字典。这是代码(我只使用pprint来很好地格式化输出SO):

from pprint import *

def allvars_bad():
    fake_temp_var = 1
    d = dict(globals())
    d.update(locals())
    return d

def foo_bad():
    x = 5
    return allvars_bad()

def foo_good():
    x = 5
    fake_temp_var = "good"
    d = dict(globals())
    d.update(locals())
    return d

pprint (foo_bad(), width=50)
pprint (foo_good(), width=50)

和输出:

 {'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'allvars_bad': <function allvars_bad at 0xb7d32b1c>,
 'd': <Recursion on dict with id=3084093748>,
 'fake_temp_var': 1,
 'foo_bad': <function foo_bad at 0xb7d329cc>,
 'foo_good': <function foo_good at 0xb7d32f0c>,
 'isreadable': <function isreadable at 0xb7d32c34>,
 'isrecursive': <function isrecursive at 0xb7d32c6c>,
 'pformat': <function pformat at 0xb7d32bc4>,
 'pprint': <function pprint at 0xb7d32b8c>,
 'saferepr': <function saferepr at 0xb7d32bfc>}
{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'allvars_bad': <function allvars_bad at 0xb7d32b1c>,
 'd': <Recursion on dict with id=3084093884>,
 'fake_temp_var': 'good',
 'foo_bad': <function foo_bad at 0xb7d329cc>,
 'foo_good': <function foo_good at 0xb7d32f0c>,
 'isreadable': <function isreadable at 0xb7d32c34>,
 'isrecursive': <function isrecursive at 0xb7d32c6c>,
 'pformat': <function pformat at 0xb7d32bc4>,
 'pprint': <function pprint at 0xb7d32b8c>,
 'saferepr': <function saferepr at 0xb7d32bfc>,
 'x': 5}

请注意,在第二个输出中,我们覆盖了fake_temp_var,并且x存在;第一个输出仅包括allvars_bad范围内的本地变量。

因此,如果要访问完整的变量范围,则不能将locals()放在另一个函数中。


我怀疑有某种框架对象,我只是没有(知道在哪里)寻找它。

这符合您的规范,我相信:

def allvars_good(offset=0):
    frame = sys._getframe(1+offset)
    d = frame.f_globals
    d.update(frame.f_locals)
    return d


def foo_good2():
    a = 1
    b = 2
    return allvars_good()

- &GT;

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d6474c>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 1,
 'allvars_bad': <function allvars_bad at 0xb7d65b54>,
 'allvars_good': <function allvars_good at 0xb7d65a04>,
 'b': 2,
 'foo_bad': <function foo_bad at 0xb7d65f44>,
 'foo_good': <function foo_good at 0xb7d65f7c>,
 'foo_good2': <function foo_good2 at 0xb7d65fb4>,
 'isreadable': <function isreadable at 0xb7d65c6c>,
 'isrecursive': <function isrecursive at 0xb7d65ca4>,
 'pformat': <function pformat at 0xb7d65bfc>,
 'pprint': <function pprint at 0xb7d65bc4>,
 'saferepr': <function saferepr at 0xb7d65c34>,
 'sys': <module 'sys' (built-in)>}

答案 2 :(得分:2)

你可以自己做:

allvars = dict()
allvars.update(globals())
allvars.update(locals())

或合并前两行:

allvars = dict(globals())
allvars.update(locals())

答案 3 :(得分:2)

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    all_vars = locals.copy()
    all_vars.update(globals())
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(all_vars)

myfunc(123)

答案 4 :(得分:1)

插入字符串以最简单的方式工作。只需列出您的变量。 Python会为你检查本地和全局。

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    print "Vars: %d, %d, %d!" % ( globalVar, paramVar, localVar )

myfunc(123)

答案 5 :(得分:0)

Python 3.5或更高版本:

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    print("Vars: {globalVar}, {paramVar}, {localVar}!".format(**{**locals(), **globals()}))

myfunc(123)