小编典典

globals()、locals() 和 vars() 有什么区别?

all

globals(),locals()和 和有什么区别vars()?他们返回什么?更新结果有用吗?


阅读 116

收藏
2022-08-16

共1个答案

小编典典

其中每一个都返回一个字典:

  • globals() 总是返回 模块 命名空间的字典
  • locals() 总是 返回 当前 命名空间 字典 __
  • 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()再次被复制进去。

两个注意事项:

  1. 这种行为是 CPython 特有的——其他 Python 可能允许更新自动返回到本地命名空间。
  2. 在 CPython 2.x 中,可以通过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__没有任何局部变量。

2022-08-16