_перегрузка _add__ operator работает не так, как ожидалось

#python #python-3.x #add

#python #python-3.x #Добавить

Вопрос:

Итак, я недавно узнал о перегрузке оператора в 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__ operator таким образом, чтобы он возвращал [p1[0] p2[0], p1[1] p2[1]] с p1 и p1 как 2 разных списка, удерживающих позиции. Я попытался добавить некоторые значения позиции, как вы можете видеть в функции updateRelativePositions , и результат странный. Для leftNozzlePos и rightNozzlePos он выводит список из 4 элементов, а для mainNozzlePos возвращает полностью неизмененные значения. Почему это происходит и как мне это исправить? Спасибо за любую помощь

Комментарии:

1. ` def __add__(p1, p2):` —> ` def __add__(self,other):`

Ответ №1:

__add__ применяется, когда вы добавляете сами экземпляры (например, выполнение ship ship или что-то еще); вы этого не делаете, вы добавляете случайные атрибуты экземпляров (что приводит к конкатенации, когда list задействованы s).

Причина mainNozzlePos не изменилась, потому что вы случайно назначили ее leftNozzlePos (перезаписав ту, которую вы вычислили двумя строками ранее).

Перегрузка оператора здесь не имеет смысла, поскольку вы не пытаетесь поддерживать добавление одного Ship к другому (что бы это вообще значило?). Вы могли бы использовать numpy массивы для своих переменных-членов, которые выполняли бы поэлементное сложение вместо конкатенации при вызове, или вы могли бы просто использовать простой вспомогательный метод для выполнения того, что вы пытаетесь сделать явно, например

 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)