【发布时间】:2011-12-19 16:12:28
【问题描述】:
globals()、locals() 和 vars() 有什么区别?他们返回什么?更新结果有用吗?
【问题讨论】:
-
可以在 python 3 中更新任何这些并让脚本真正工作吗?
标签: python
globals()、locals() 和 vars() 有什么区别?他们返回什么?更新结果有用吗?
【问题讨论】:
标签: python
每个都返回一个字典:
globals() always 返回 module 命名空间的字典locals() always 返回 当前 命名空间的 a 字典vars() 返回一个当前命名空间的字典(如果不带参数调用)或参数的字典。locals 和vars 可以使用更多解释。如果在函数内部调用locals(),它会使用当前局部变量命名空间(加上任何闭包变量)的值更新字典并返回它。在同一个堆栈帧中多次调用locals() 每次都会返回相同的字典——它作为f_locals 属性附加到堆栈帧对象。 dict 的内容会在每个locals() 调用和每个f_locals 属性访问时更新,但仅 在此类调用或属性访问时更新。变量赋值时不会自动更新,在dict中赋值条目也不会赋值对应的局部变量:
import inspect
def f():
x = 1
l = locals()
print(l)
locals()
print(l)
x = 2
print(x, l['x'])
l['x'] = 3
print(x, l['x'])
inspect.currentframe().f_locals
print(x, l['x'])
f()
给我们:
{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2
第一个print(l) 只显示一个'x' 条目,因为对l 的分配发生在locals() 调用之后。第二个print(l),在再次调用locals() 之后,显示l 条目,即使我们没有保存返回值。第三个和第四个prints表示赋值变量不会更新l,反之亦然,但是我们访问f_locals后,局部变量又被复制到locals()中。
两个音符:
exec "pass" 行来完成这项工作。这会将函数切换到较旧、较慢的执行模式,该模式使用 locals() dict 作为局部变量的规范表示。如果locals() 在外部 一个函数被调用,它会返回作为当前命名空间的实际字典。对命名空间的进一步更改反映在字典中,对字典的更改反映在命名空间中:
class Test(object):
a = 'one'
b = 'two'
huh = locals()
c = 'three'
huh['d'] = 'four'
print huh
给我们:
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
到目前为止,我所说的关于 locals() 的所有内容都适用于 vars()... 不同之处在于:vars() 接受单个对象作为参数,如果你给它一个对象,它会返回该对象的__dict__。对于一个典型的对象,它的__dict__ 是其大部分属性数据的存储位置。这包括类变量和模块全局变量:
class Test(object):
a = 'one'
b = 'two'
def frobber(self):
print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()
这给了我们:
three
请注意,函数的__dict__ 是它的属性命名空间,而不是局部变量。函数的 __dict__ 存储局部变量是没有意义的,因为递归和多线程意味着可以同时对函数进行多次调用,每个调用都有自己的局部变量:
def f(outer):
if outer:
f(False)
print('Outer call locals:', locals())
print('f.__dict__:', f.__dict__)
else:
print('Inner call locals:', locals())
print('f.__dict__:', f.__dict__)
f.x = 3
f(True)
这给了我们:
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
这里,f 递归调用自身,因此内部和外部调用重叠。每个调用locals() 时看到自己的局部变量,但两个调用看到相同的f.__dict__,而f.__dict__ 中没有任何局部变量。
【讨论】:
eval(),您可以访问添加到函数内调用的 vars() 或 locals() 字典中的变量。例如:def test(): huh = locals(); huh['d'] = 4; print eval('d') 在执行 test() 时打印 4!
dict(由locals()返回)恰好反映在本地命名空间中,而对本地命名空间的更改恰好反映在dict中(在我的python中) .唯一的问题是规范不保证这种行为。
import this 和谷歌site:docs.python.org namespace