Python 提供就地运算符(+=、*=、/=、@= 等)来提高更改变量时的内存效率。但是,您要修改的变量始终位于运算符的“左侧”:
a /= b
等于 a = a*b
,而不是 a = b*a
。在此示例中,这并不重要,因为乘法是可交换的。然而,对于像减法、除法和(特别是对我来说)矩阵乘法这样的非交换运算,如何反转这个顺序呢?比如:
a -= b # -> a = a-b
a =- b # -> a = b-a
在大多数情况下,我不会费心使用内联运算,但我正在模拟刚体,并且必须尽可能高效地执行大量矩阵运算。
要评估效果和选项,您可以使用如下内容:
# https://medium.com/@noransaber685/demystifying-python-bytecode-a-guide-to-understanding-and-analyzing-code-execution-6a163cb83bd1
import dis
# https://www.pythoninformer.com/python-language/magic-methods/in-place-operator-overload/
class Matrix:
def __init__(self, a, b, c, d):
self.data = [a, b, c, d]
def __str__(self):
return '[{}, {}][{}, {}]'.format(self.data[0],
self.data[1],
self.data[2],
self.data[3])
def __add__(self, other):
if isinstance(other, Matrix):
return Matrix(self.data[0] + other.data[0],
self.data[1] + other.data[1],
self.data[2] + other.data[2],
self.data[3] + other.data[3])
else:
return NotImplemented
def __iadd__(self, other):
if isinstance(other, Matrix):
self.data[0] += other.data[0]
self.data[1] += other.data[1]
self.data[2] += other.data[2]
self.data[3] += other.data[3]
return self
else:
return NotImplemented
ma = Matrix(1, 2, 3, 4)
mb = Matrix(5, 6, 7, 8)
def f1():
ma += mb
def f2():
ma = ma + mb
def f3():
ma = mb + ma
print("f1:")
dis.dis(f1)
print("f2:")
dis.dis(f2)
print("f3:")
dis.dis(f3)
输出:
f1:
39 0 LOAD_FAST 0 (ma)
2 LOAD_GLOBAL 0 (mb)
4 INPLACE_ADD
6 STORE_FAST 0 (ma)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
f2:
42 0 LOAD_FAST 0 (ma)
2 LOAD_GLOBAL 0 (mb)
4 BINARY_ADD
6 STORE_FAST 0 (ma)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
f3:
45 0 LOAD_GLOBAL 0 (mb)
2 LOAD_FAST 0 (ma)
4 BINARY_ADD
6 STORE_FAST 0 (ma)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
主要区别在于(临时)变量的存储/加载操作。就运行时间而言,这些应该比实际计算花费的时间更少。