Python列表中+=与+运算符的差异及底层机制解析
Python列表中
+=与+运算符的行为差异及底层机制 我发现Python里对列表使用+=和+运算符时,行为存在明显差异,先看两个代码案例:
案例1:使用+=时对象引用不变
x = [1, 2] y = x x += [3] y += [4] print(x is y) # 输出 True
这里输出True,说明x和y始终指向内存中的同一个对象。
案例2:混用+=和+时对象引用改变
x = [1, 2] y = x x += [3] y = y + [4] print(x is y) # 输出 False
输出变成False,说明执行y = y + [4]后,y指向了新的对象,不再和x指向同一内存地址。很多人误以为+=只是列表拼接的语法糖,但实际行为和这一认知不符,下面通过反编译拆解两者的底层逻辑。
底层机制验证:使用dis模块反编译
我用dis模块反编译了两个函数,对比两者的字节码指令:
from dis import dis def use_inplace_add(list): list += [3] return list def use_regular_add(list): list = list + [3] return list dis(use_inplace_add) # 返回结果: """ 1 0 RESUME 0 2 2 LOAD_FAST 0 (list) 4 LOAD_CONST 1 (3) 6 BUILD_LIST 1 8 BINARY_OP 13 (+=) 12 STORE_FAST 0 (list) 4 14 LOAD_FAST 0 (list) 16 RETURN_VALUE """ dis(use_regular_add) # 返回结果: """ 1 0 RESUME 0 2 2 LOAD_FAST 0 (list) 4 LOAD_CONST 1 (3) 6 BUILD_LIST 1 8 BINARY_OP 0 (+) 12 STORE_FAST 0 (list) 4 14 LOAD_FAST 0 (list) 16 RETURN_VALUE """
对比反编译结果,核心差异在第8行的字节码指令:
use_inplace_add: 8 BINARY_OP 13 (+=) use_regular_add: 8 BINARY_OP 0 (+)
字节码指令解析
BINARY_OP 13 (+=):执行原地加法,直接修改原对象内存中的内容,之后将修改后的对象重新绑定到变量。对列表来说,这一操作等价于调用list.extend(),不会创建新的列表对象。BINARY_OP 0 (+):执行常规加法,不会修改原对象,而是在内存中创建一个全新的列表,将两个列表的内容拼接后存入新对象,最后将新对象绑定到变量。
内容的提问来源于stack exchange,提问作者Zimzozaur
相关产品推荐
相关产品推荐

