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()

注二:

  • 这种行为是特定于CPython的——其他python可能允许更新自动将其返回到本地名称空间
  • 在CPython 2.x中,可以通过在函数中放入
    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中更新其中任何一个并让脚本实际工作吗?