__add__ 运算符重载未按预期工作

__add__ operator overloading does not work as expected

所以我最近在 python 中了解了运算符重载,并尝试在我正在从事的项目中使用它。贝娄,我试图重现我遇到的问题。

class Ship:
    def __init__(self, pos):
        self.pos = pos
        self.center = [18, 30]
        self.leftNozzlePos = [6, 10]
        self.rightNozzlePos = [30, 10]
        self.mainNozzlePos = [18, 60]

    def __add__(p1, p2):
        x = p1[0] + p2[0]
        y = p1[1] + p2[1]
        return [x, y]

    def updateRelativePositions(self):
        self.center = self.pos + self.center
        self.leftNozzlePos = self.pos + self.leftNozzlePos
        self.rightNozzlePos = self.pos + self.rightNozzlePos
        self.leftNozzlePos = self.pos + self.mainNozzlePos

ship = Ship([600, 300])
ship.updateRelativePositions()
print(ship.mainNozzlePos)

所以我有一堆位置值存储在列表中作为 [x, y]。我试图重载 __add__ 运算符,使其 returns [p1[0]+p2[0], p1[1]+p2[1]]p1p1 是 2 个不同的列表持有位置。我尝试添加一些位置值,正如您在函数 updateRelativePositions 中看到的那样,结果很奇怪。对于 leftNozzlePosrightNozzlePos 它打印一个包含 4 个项目的列表,对于 mainNozzlePos 它 returns 完全不变的值。为什么会发生这种情况,我该如何解决?感谢您的帮助

__add__ 适用于您自己添加实例(例如 ship + ship 或其他);你不是,你正在添加实例的随机属性(当涉及 lists 时会导致连接)。

mainNozzlePos 未更改的原因是您不小心将其分配给了 leftNozzlePos(覆盖了您之前两行计算的那个)。

运算符重载在这里没有意义,因为您不想支持将一个 Ship 添加到另一个(那甚至意味着什么?)。您可以将 numpy 数组用于您的成员变量,这将在调用 + 时执行 element-wise 加法而不是连接,或者您可以只使用一个简单的辅助方法来执行您想要的操作尝试明确地做,例如

class Ship:
    # __init__ omitted for brevity

    @staticmethod
    def _addpoints(p1, p2):
        x = p1[0] + p2[0]
        y = p1[1] + p2[1]
        return [x, y]

    def updateRelativePositions(self):
        self.center = self._addpoints(self.pos, self.center)
        self.leftNozzlePos = self._addpoints(self.pos, self.leftNozzlePos)
        self.rightNozzlePos = self._addpoints(self.pos, self.rightNozzlePos)
        self.mainNozzlePos = self._addpoints(self.pos, self.mainNozzlePos)

或者,您可以定义:

    def _addpos(self, pt):
        pt[0] += self.pos[0]
        pt[1] += self.pos[1]

并避免在每次调用时显式传递 self.pos (代价是使函数只添加 self.pos 到事物,而不是任意点)并且需要在最后重新分配,进行调用简化为:

    def updateRelativePositions(self):
        self._addpos(self.center)
        self._addpos(self.leftNozzlePos)
        self._addpos(self.rightNozzlePos)
        self._addpos(self.mainNozzlePos)