代码之家  ›  专栏  ›  技术社区  ›  qbot

对函数中globals()行为的文档感到困惑

  •  1
  • qbot  · 技术社区  · 11 月前

    根据 Python documentation 属于 globals() :

    对于函数内的代码,这是 在定义函数时设置,并保持不变 不管函数在哪里被调用。

    我理解这是在呼唤 globals() 从函数内部返回一个与定义函数时表示全局名称空间的字典相同的字典,即使从那以后全局名称空间发生了修改。

    然而,我下面的实验表明,我的理解显然是不正确的。 那么,文件是什么意思呢?

    (在下面的示例中,我预计第二次调用 foo() 以给出与第一个相同的结果。当然,如果是这样的话,我会质疑 globals() ,但这似乎就是文档的含义。)

    def foo():
        if 'x' in globals():
            print(f"Found x: {globals()['x']}")
        else:
            global x
            x = 1
            print(f"Not found. Set x = {x}.")
    
    foo() # Not found. Set x = 1.
    foo() # Found x: 1
    
    1 回复  |  直到 11 月前
        1
  •  1
  •   Serge Ballesta    11 月前

    事实上,这个问题与 globals() 内置功能,但与行为更密切相关 可变的 物体。

    长话短说,你的 观察 是正确的,文件是绝对正确和准确的。

    根本原因是Python变量只是 参考文献 到实际对象。让我们来看一个例子:

    a = {'a': 1, 'b': 2}
    b = a                 # ok, we take a "copy"
    print(b)
    {'a': 1, 'b': 2}      # no surprise here
    a['c'] = 3            # let us MUTATE the original object
    print(b)
    {'a': 1, 'b': 2, 'c': 3}
    

    这里发生的事情是,这两个变量都是对同一个对象的引用,可以用 print(id(a), id(b))

    但如果我们使用不同的对象:

    a = {'a': 1, 'b': 2, 'c': 3}     # a is now a new and distinct object
                                     #  even if it has the same value
    a['d'] = 4    
    print(a, b)
    {'a': 1, 'b': 2, 'c': 3, 'd': 4} {'a': 1, 'b': 2, 'c': 3}
    

    b 仍然是对原始对象的引用,因此新对象更改为 a 无法通过访问 b 。您可以通过以下方式确认它们现在是不同的对象 打印(id(a),id(b)) .

    该文档只是一个警告,如果出于任何原因将全局目录更改为新的不同对象 (*) ,函数仍将保留定义函数时存在的对象的引用。


    (*) AFAIK,该语言的规范并不能保证全局目录在整个程序生命周期内都是相同的对象