Python 反转非交换就地运算符的元素顺序

问题描述 投票:0回答:1

Python 提供就地运算符(+=、*=、/=、@= 等)来提高更改变量时的内存效率。但是,您要修改的变量始终位于运算符的“左侧”:

a /= b
等于
a = a*b
,而不是
a = b*a
。在此示例中,这并不重要,因为乘法是可交换的。然而,对于像减法、除法和(特别是对我来说)矩阵乘法这样的非交换运算,如何反转这个顺序呢?比如:

a -= b # -> a = a-b
a =- b # -> a = b-a

在大多数情况下,我不会费心使用内联运算,但我正在模拟刚体,并且必须尽可能高效地执行大量矩阵运算。

python-3.x matrix-multiplication in-place
1个回答
0
投票

要评估效果和选项,您可以使用如下内容:

# 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

主要区别在于(临时)变量的存储/加载操作。就运行时间而言,这些应该比实际计算花费的时间更少。

© www.soinside.com 2019 - 2024. All rights reserved.