如何反转Python非交换原地运算符的操作数顺序?
解决原地运算符反向操作数的高效实现问题
Python的原地运算符(+=、-=、@=等)默认基于左操作数修改,对应a = a op b的逻辑,但对于减法、矩阵乘法这类非交换操作,要实现a = b op a的高效原地修改,可按以下方式处理:
1. 利用数值库的out参数(最优解)
如果使用numpy、PyTorch这类常用数值库,它们的核心运算函数大多支持out参数,能直接将运算结果写入目标变量的内存,完全避免临时对象创建,最适合刚体模拟这类需要大量高效矩阵运算的场景:
import numpy as np # 原地实现 a = b - a a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) np.subtract(b, a, out=a) # 直接在a的内存中写入b-a的结果 # 原地实现 a = b @ a(矩阵乘法) np.matmul(b, a, out=a)
PyTorch用法类似,比如torch.sub(b, a, out=a)、torch.matmul(b, a, out=a),同样是原地修改。
2. 切片赋值(通用折中方案)
如果库不支持out参数,或者使用支持切片的序列类型(比如numpy数组、列表),可以用切片赋值复用原变量的内存空间:
# 原地实现 a = b - a(numpy数组) a[:] = b - a # 对于自定义可切片矩阵类,也可套用类似逻辑 a[:] = b @ a
这种方式会先创建临时存储运算结果的对象,但随后直接覆盖原变量内存,比a = b op a更节省内存(后者会让原变量内存进入垃圾回收流程,而切片赋值复用原内存)。
3. 自定义类的专属原地方法
如果是自行实现的矩阵类,可以编写专门的原地修改方法处理反向操作,完全避免额外内存分配:
class RigidBodyMatrix: def __init__(self, data): # 假设用二维列表存储矩阵数据 self.data = [row.copy() for row in data] def inplace_r_sub(self, other): # 原地修改为 other - self for i in range(len(self.data)): for j in range(len(self.data[i])): self.data[i][j] = other.data[i][j] - self.data[i][j] def inplace_r_matmul(self, other): # 原地修改为 other @ self # 手动实现矩阵乘法并写入自身内存(避免临时矩阵) size = len(self.data) temp_row = [0]*size for i in range(size): for k in range(size): temp_row[k] = other.data[i][k] for j in range(size): val = 0 for k in range(size): val += temp_row[k] * self.data[k][j] self.data[i][j] = val # 使用示例 a = RigidBodyMatrix([[1,2],[3,4]]) b = RigidBodyMatrix([[5,6],[7,8]]) a.inplace_r_sub(b) # 原地修改a为b-a a.inplace_r_matmul(b) # 原地修改a为b@a
这种方式完全自定义内存操作,适合对性能有极致要求的场景,但需要手动实现运算逻辑。
内容的提问来源于stack exchange,提问作者Koos Naamloos
相关产品推荐
相关产品推荐

