【问题标题】:Python global and local variablesPython 全局变量和局部变量
【发布时间】:2024-01-06 02:57:01
【问题描述】:

在 Python 2.7 中,运行以下代码:

def f():
    a = a + 1

f()

给出以下结果:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    f()
  File "test.py", line 2, in f
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

但如果我将代码更改为以下:

def f():
    a[0] = a[0] + 1

f()

我得到不同的错误:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    f()
  File "test.py", line 2, in f
    a[0] = a[0] + 1
NameError: global name 'a' is not defined

为什么当aint 时,Python 认为a 是局部变量,而当list 时是全局变量?这背后的原理是什么?

P.S.:我在阅读 this thread 后进行实验。

【问题讨论】:

    标签: python scope global-variables


    【解决方案1】:

    密钥在the assignment statement的文档中找到:

    将对象分配给单个目标被递归定义为 跟随。

    如果目标是标识符(名称)(例如a = a + 1

    • 如果名称没有出现在当前代码的全局语句中 块:名称绑定到当前本地命名空间中的对象。
    • 否则:名称绑定到当前全局中的对象 命名空间。

    如果名称已经绑定,则为反弹。这可能会导致 先前绑定到名称的对象的引用计数 达到零,导致对象被释放及其析构函数 (如果有的话)被调用。

    ...

    如果目标是订阅(例如a[0] = a[0] + 1: 参考被评估。它应该产生一个可变序列 对象(例如列表)或映射对象(例如字典)。 接下来,计算下标表达式。

    f1 Python 看到您正在将某个值绑定到a,看到a 尚未在此范围内的global a 语句中使用并准备一个本地多变的。然后它尝试计算表达式a + 1,查找变量a,并找到一个未初始化的局部变量。这导致UnboundLocalError

    f2 Python 看到您正在为变量a 的订阅分配一些值。它在本地命名空间中查找该变量,但找不到它。然后它沿着非本地命名空间(闭包)向上走,直到到达全局命名空间。一旦在全局命名空间中找不到a,它就会抛出NameError

    【讨论】:

    • 我认为错误与g中的赋值无关。我已经编辑了删除不相关陈述的问题。
    • @fossilet - 很抱歉我弄错了你的问题 - 我已经更新了我的答案,如果有帮助请告诉我。
    【解决方案2】:

    你可以尝试做这样的事情吗:

    def f(a):
        a += 1
        print a
    
    def g():
        a = 3
        f(a)
    
    g()
    

    【讨论】: