#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)