globals()、locals() 和 vars() 之间有什么区别?
- 2024-12-25 08:51:00
- admin 原创
- 128
问题描述:
globals()
、locals()
和之间有什么区别vars()
?它们返回什么?结果更新有用吗?
解决方案 1:
每个都返回一本字典:
globals()
总是返回模块命名空间的字典locals()
始终返回当前命名空间的字典vars()
返回当前命名空间的字典(如果没有参数调用)或参数的字典。
locals
并且vars
可以使用更多解释。如果locals()
在函数内部调用,它会使用当前局部变量命名空间(加上任何闭包变量)的值更新字典并返回它。locals()
在同一个堆栈框架中多次调用每次都会返回同一个字典 - 它作为其属性附加到堆栈框架对象f_locals
。字典的内容会在每次locals()
调用和每次f_locals
属性访问时更新,但仅在此类调用或属性访问时更新。分配变量时不会自动更新,并且分配字典中的条目不会分配相应的局部变量:
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
条目,尽管我们没有保存返回值。第三个和第四个print
显示赋值变量不会更新l
,反之亦然,但在我们访问之后f_locals
,局部变量被再次复制到locals()
。
两点说明:
此行为是 CPython 特有的——其他 Python 可能允许更新自动返回到本地命名空间。
在 CPython 2.x 中,可以通过
exec "pass"
在函数中添加一行来实现这一点。这会将函数切换到较旧、较慢的执行模式,该模式使用字典locals()
作为局部变量的规范表示。
如果在函数外部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__
其中没有任何局部变量。