global
仅在尝试更改变量引用的对象时才需要。因为vals[0] = 5
更改的是实际对象而不是参考,所以不会引发任何错误。但是,使用vals += [5, 6]
,解释器会尝试查找局部变量,因为它无法更改全局变量。
令人困惑的是,将+=
运算符与list一起使用会修改原始列表,例如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
我们可以看到功能a
和c
用途LOAD_GLOBAL
,而b
尝试使用LOAD_FAST
。现在我们可以看到为什么使用+=
不起作用的原因- 解释器尝试将其v
作为局部变量加载,因为它是就地添加的默认行为。由于它不知道是否v
为列表,因此基本上假设该行的含义与相同v = v + [1]
。