Python中+=和普通+的区别
在 Python 开发(特别是使用 PyTorch 进行深度学习训练)时,许多人认为 a = a + b 和 a += b 是完全等价的。但在底层内存管理和性能表现上,它们有着本质的区别。理解这一点,对于优化数据处理管道和避免显存碎片化至关重要。
先看结论:
a + b:创建新对象,不会修改原变量a,只是返回相加结果a += b:原地修改(增量赋值),优先修改变量本身;分可变数据类型、不可变数据类型两种情况
一、可变数据类型与不可变数据类型
Python3 中有六个标准的数据类型:
- Number(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Set(集合)
- Dictionary(字典)
其中:
- 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
- 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
1.1 不可变数据类型
当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。
1 | |
1.2 可变数据类型
当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。
1 | |
二、+=和普通加法
刚才研究了可变数据类型和不可变数据类型,下面回到加法的讨论。
1 | |
这里要注意一点:普通数字/字符串是不可变对象,而
torch.Tensor是可变容器对象,支持原地运算+=。
tensor += n:原地自增,不新建张量tensor = tensor + n:先计算tensor + n得到新张量,再把局部变量data指向新张量,和外部原张量断开关联
由此可以看出,data = data + 2 这里其实是生成了一个全新的 tensor,然后将局部变量 data 重新绑定到这个新张量上,而原来外部 x 指向的张量没有发生变化,依旧是 [3, 4]。
data += 2对应方法__iadd__(原地加法)
Tensor 实现了原地加法,逻辑:
直接在当前张量内存中修改数值,不分配新内存
适用于 list、tensor、array 这类可变对象。
data = data + 2对应方法__add__(普通加法)
普通加法一定会创建新对象,流程:
- 计算
data + 2,开辟新内存存储结果 - 局部变量
data放弃原有指向,绑定到新张量 - 函数外的原变量 x 不受任何影响
三、应用
为了方便进行原位操作,PyTorch 中的函数可以在调用之后加下划线,强调这是进行原位操作(在模型训练中经常用到的 w.grad.zero() 即为原位更新,注意 _ 是放在()之前的),简单得用上述例子进行实现,上述操作也可以这样使用:
1 | |
需要注意的是,此种用下划线 _ 的原位操作方法在面对叶子节点的时候不可以使用。因为叶子节点在迭代过程中需要被用到其他量或梯度的求解,不允许被更改,如果轻易被修改,会导致其他的值计算错误。
Python中+=和普通+的区别
http://example.com/2026/06/13/Pythonh中-和普通-的区别/