如图,第三个函数中,全局变量 a 为何被当做局部变量了,与前两个函数有什么不一样?
(第一次发图不知道能不能显示出来,多写一种格式试试)
https://imgur.com/SJzAH2m
1
f1ush 2023-03-20 22:45:23 +08:00 1
https://imgur.com/a/vYwLyHl
看了一下 Python 字节码,可以看到 aa 和 bb 都是编译成了全局变量了,cc 编译出来是局部变量; 个人猜测:Python 看到没有出现过的变量名会先去全局找,但是看到 += 符号的时候回默认前面的变量是已经出现过的本地变量 |
2
hsfzxjy 2023-03-20 22:47:25 +08:00 via Android
这种情况下,加一句 global a 或 nonlocal a
|
3
wynemo 2023-03-20 22:47:52 +08:00
>>> a = 5
>>> id(a) 4349762296 >>> a += 6 >>> id(a) 4349762488 因为生成新的对象了吧 The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global. |
4
llsquaer 2023-03-20 23:03:28 +08:00
a 是列表 容器可变类型 , 内存地址指向没有变.所以可以在函数内部修改..如果你把 a 改为 字符串..就改不了.
基础问题. 你需要先了解 可变类型 和 不可变类型的区别. 最后一个函数是 += 是累加赋值的意思. 列表确实是可以用+号扩展的. 写全就是 a= 1 + a 这个问题是 函数局部变量 a 还没有赋值, 函数内部是优先内部变量处理. a= 这个时候可以理解为暂存的变量,没有值,还没划分内存地址. =号后面才是真正的值.. 后面的 +a 加的是局部变量 a , 所以报错.. 因为你 + 的是还没值的自己.. |
5
iOCZ 2023-03-20 23:14:48 +08:00
引用 a 是全局的,但是赋值 a 的话,得加 global
|
6
DOLLOR 2023-03-20 23:18:33 +08:00
这就是个陷阱。
+=跟=一样,都会声明新的本地变量,所以第三个函数里的 a 其实是局部变量,而非外部的 a 。 再一个更简单的例子: a = 1 def f1(): 𰻝# 报错,此处的 a 不是外部的 a 𰻝a += 1 f1() 回避方式: a = 1 def f1(): 𰻝global a 𰻝a += 1 f1() print(a) |
7
mylifcc 2023-03-21 00:21:42 +08:00 1
list 的加法 要用 a[:] += [3],如果使用 a += [3] 这种语法,则会创建一个新的列表对象,并将其赋值给 a 变量,而不是修改原始列表。
|
8
mylifcc 2023-03-21 01:01:35 +08:00
|
9
zzl22100048 2023-03-21 08:25:33 +08:00 1
@mylifcc 不对吧,list += 会调用 __iadd__ 后做一个赋值,内部实际执行的是 extend 方法 并返回 self ,并没有创建新的列表对象。
他这里用+= 对变量赋值了,导致函数内部会将 a 解析为局部变量 |
10
aijam 2023-03-21 12:48:10 +08:00 1
|
11
lovelylain 2023-03-21 12:55:05 +08:00 via Android 1
a += x 相当于 a = a.__iadd__(x),对变量 a 重新赋值了,所以在没有 global 或 nonlocal 显式声明时被当做 local 变量,不过感觉这个不是很合理呀,因为 python 未定义变量是没法+=的,肯定是有在前面有=或者 import 赋值才行,既然这样+=就不应该作为变量是否本地的依据。
|