python - 在 Python 中写入(而不是)全局变量

标签 python python-2.7 global-variables python-internals

来自不太动态的 C++,我在理解这段 Python (2.7) 代码的行为时遇到了一些困难。

注意:我知道这是糟糕的编程风格/邪恶的,但我还是想理解它。

vals = [1,2,3]

def f():
    vals[0] = 5
    print 'inside', vals

print 'outside', vals
f()
print 'outside', vals

此代码运行无误,f 操纵(看似)全局列表。这与我之前的理解相反,即要在函数中操作(而不仅仅是读取)的全局变量必须声明为 global ...

另一方面,如果我将 vals[0] = 5 替换为 vals += [5,6],执行将失败并出现 UnboundLocalError 除非我将 global vals 添加到 f。这也是我预计在第一种情况下会发生的情况。

您能解释一下这种行为吗?

为什么我可以在第一种情况下操作vals?为什么第二种操作会失败而第一种不会?

更新: 在评论中指出 vals.extend(...) 无需 global 即可工作。这让我更加困惑 - 为什么 += 与调用 extend 的方式不同?

最佳答案

global 仅在您尝试更改变量引用的对象时才需要。因为 vals[0] = 5 更改了实际对象而不是引用,所以不会引发错误。但是,对于 vals += [5, 6],解释器会尝试查找局部变量,因为它无法更改全局变量。

令人困惑的是,对列表使用+= 运算符会修改原始列表,如vals[0] = 5。而 vals += [5, 6] 失败,vals.extend([5, 6]) 有效。我们可以寻求dis.dis的帮助借给我们一些线索。

>>> def a(): v[0] = 1
>>> def b(): v += [1]
>>> def c(): v.extend([1])
>>> import dis
>>> dis.dis(a)
  1           0 LOAD_CONST               1 (1)
              3 LOAD_GLOBAL              0 (v)
              6 LOAD_CONST               2 (0)
              9 STORE_SUBSCR        
             10 LOAD_CONST               0 (None)
             13 RETURN_VALUE        
>>> dis.dis(b)
  1           0 LOAD_FAST                0 (v)
              3 LOAD_CONST               1 (1)
              6 BUILD_LIST               1
              9 INPLACE_ADD         
             10 STORE_FAST               0 (v)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        
d
>>> dis.dis(c)
  1           0 LOAD_GLOBAL              0 (v)
              3 LOAD_ATTR                1 (extend)
              6 LOAD_CONST               1 (1)
              9 BUILD_LIST               1
             12 CALL_FUNCTION            1
             15 POP_TOP             
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

我们可以看到函数 ac 使用 LOAD_GLOBAL,而 b 尝试使用 LOAD_FAST。我们现在可以看到为什么使用 += 不起作用 - 解释器尝试将 v 作为局部变量加载,因为它是就地添加的默认行为。因为它不知道 v 是否是一个列表,所以它基本上假定该行与 v = v + [1] 的含义相同。

关于python - 在 Python 中写入(而不是)全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20771487/

相关文章:

python - 当我尝试发送控制更改消息时,MIDI 消息数据无效

c - 在 C 中,如何计算一个函数中的局部变量,在另一个函数中?

Python 类和全局变量与局部变量

python - 如何使用 igraph 在 python 中创建具有顶点权重的图?

python - Python 中的信号拟合模型

python - 在正则表达式中使用非贪婪限定符 '*?'

Python组合生成

c++ - 确保全局记录器对象的生命周期比其他全局对象长

python - 为什么我的图像按钮没有出现?

python - Django 模型表单未生成预期的 HTML