关于python:获取当前作用域中所有变量及其值的dict

Get a dict of all variables currently in scope and their values

请考虑以下代码段:

1
2
3
4
5
6
7
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()来达到这个目的。这是否总是正确的,或者该表达式是否会错误地处理某些角情况?

重写以澄清问题。


像你这样合并两个dict的最好方法(当地人压倒全球)是dict(globals(), **locals())

合并全局和局部的方法缺少的是(a)内置(我认为这是故意的,即您不认为内置是"变量"……但是,如果你选择的话,他们可能是!-,和(b)如果您在嵌套函数中,那么任何一个封闭函数局部的变量(对于所有这些变量来说,没有真正好的方法来获得dict,加上——只有那些在嵌套函数中显式访问的变量,即其中的"自由变量",仍然作为闭包中的单元格存在。

我认为这些问题对于您的预期用途来说并不是什么大问题,但是您确实提到了"角落案例";-)。如果您需要覆盖它们,有一些方法可以获得内置(这很容易)和(不太容易)所有单元(嵌套函数中明确提到的封闭函数的变量——thefunction.func_code.co_freevars以获取名称,thefunction.func_closure以获取单元,cell_contents以获取每个单元的值)。(但请记住,这些变量只能是嵌套函数代码中显式访问的封闭函数的变量!).


这是你想要的吗?

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

如果我正确阅读了文档,您将创建一份globals()dict的副本,然后覆盖任何副本,并插入来自locals()dict的新条目(因为locals()无论如何应该在您的范围内具有优先权)。

我还没有找到合适的函数来返回调用函数范围内变量的完整字典。这是代码(我只使用pprint为so格式化输出):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 {'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范围内的本地var。

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


我怀疑有什么框架物体,我只是不知道在哪里找。

我相信这符合你的要求:

1
2
3
4
5
6
7
8
9
10
11
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()

-->

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{'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)>}


1
2
3
4
5
6
7
8
9
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)

你可以自己做:

1
2
3
allvars = dict()
allvars.update(globals())
allvars.update(locals())

或者结合前两行:

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

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

1
2
3
4
5
6
7
globalVar = 25

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

myfunc(123)