Python 什么';globals()、locals()和vars()之间的区别是什么?
Python 什么';globals()、locals()和vars()之间的区别是什么?,python,Python,globals()、locals()和vars()之间有什么区别?他们返回什么?对结果的更新有用吗?每个结果都返回一个字典: globals()始终返回模块命名空间的字典 locals()始终返回当前命名空间的字典 vars()返回当前命名空间的字典(如果没有参数调用)或参数的字典 locals和vars需要更多的解释。如果在函数中调用了locals(),它将使用当前局部变量名称空间(加上任何闭包变量)的值更新dict,并返回它。在同一堆栈帧中多次调用locals(),每次都返回相同的dic
globals()
、locals()
和vars()
之间有什么区别?他们返回什么?对结果的更新有用吗?每个结果都返回一个字典:
始终返回模块命名空间的字典globals()
始终返回当前命名空间的字典locals()
返回当前命名空间的字典(如果没有参数调用)或参数的字典vars()
locals
和vars
需要更多的解释。如果在函数中调用了locals()
,它将使用当前局部变量名称空间(加上任何闭包变量)的值更新dict,并返回它。在同一堆栈帧中多次调用locals()
,每次都返回相同的dict-它作为其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
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
three
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
第一个print(l)
仅显示'x'
条目,因为l
的赋值发生在locals()
调用之后。第二个print(l)
,在再次调用locals()
之后,显示一个l
条目,即使我们没有保存返回值。第三个和第四个print
s显示赋值变量不会更新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
给了我们:
{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
three
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
到目前为止,我所说的关于locals()
的一切对于vars()
也是正确的。。。区别在于:vars()
接受单个对象作为其参数,如果给它一个对象,它将返回该对象的\u dict\u
。对于典型对象,其\uuuu dict\uuu
是其大部分属性数据的存储位置。这包括类变量和模块全局变量:
class Test(object):
a = 'one'
b = 'two'
def frobber(self):
print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()
这给了我们:
three
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
请注意,函数的\uuu dict\uu
是其属性名称空间,而不是局部变量。函数的\uuu dict\uuu
存储局部变量是没有意义的,因为递归和多线程意味着可以同时对函数进行多个调用,每个调用都有自己的局部变量:
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)
这给了我们:
three
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
在这里,
f
递归地调用自身,因此内部调用和外部调用重叠。当调用locals()
时,每个调用都会看到自己的局部变量,但两个调用都会看到相同的f.uu dict_uu
,并且f.u dict_uu
中没有任何局部变量。可能会使用“和字典的任何赋值都不会反映在实际的局部名称空间中”这样的措辞,如果使用eval()
,则可以访问添加到函数内调用的vars()
或locals()
字典中的变量。例如:def test():huh=locals();嗯【'd']=4;当执行test()
时,print eval('d')
打印4!实际上,对dict
(由locals()
返回)的赋值恰好反映在本地名称空间中,而对本地名称空间的更改恰好反映在dict
(在我的python中)。唯一的问题是规范不能保证这种行为。术语名称范围的使用对我来说比名称空间更容易。@overexchange:导入这个
,在google站点:docs.python.org名称空间
中,可以在python 3中更新其中任何一个并让脚本实际工作吗?