Могу ли я использовать перегруженный оператор в объявлении класса? - PullRequest
0 голосов
/ 10 ноября 2019

Я пытаюсь создать простой класс Vector в python и понял, что не могу использовать ранее перегруженный оператор в методе, как в c ++. У меня есть какая-то ошибка? или как работает python?

class Vector3D:
    #constructor
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z
    #overloading division operator for just numbers
    def __div__(self,other):
        if type(other) == int or type(other) == float:
            return Vector3D(self.x/other,self.y/other,self.z/other)
        print("Error")
        return
    #Used in the normalize method
    def Magnitude(self):
        return math.sqrt(self.x**2+ self.y**2 + self.z**2)
    # ==> using the division operator in normalization
    def Normalize(self):
        return self / self.Magnitude()
    # <== Throws: TypeError: unsupported operand type(s) for /: 'Vector3D' and 'float'

РЕДАКТИРОВАНИЕ РЕШЕНО (спасибо @ user2357112 и @jirassimok):

class Vector3D:
    #constructor
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z
    def __truediv__(self,other):
        if isinstance(other,numbers.Number):
            return Vector3D(self.x/other,self.y/other,self.z/other)
        print("Error")
        return
    def Magnitude(self):
        return math.sqrt(self.x**2+ self.y**2 + self.z**2)
    # ==> using the division operator in normalization
    def Normalize(self):
        return self / self.Magnitude()

1 Ответ

1 голос
/ 10 ноября 2019

В Python 3 1 используйте __truediv__ для / и __floordiv__ для (//).

Это также работает в Python 2 с from __future__ import division (что приводит к тому, что деление ведет себя как в Python 3).


Вот два дополнительных совета:

Во-первых, вместо проверки точных типов float и int,вы можете использовать классы в модуле numbers для проверки числовых типов.

Во-вторых, вы должны вернуть NotImplemented из переопределенного двоичного оператора, если он не знает, что делатьделать с заданным значением. Затем Python проверит, реализует ли другой операнд перевернутую версию оператора (т. Е. __r[name]__), и попытается это сделать. Если это также возвращает NotImplemented, Python повысит TypeError. Это позволяет создавать классы, которые можно использовать с обеих сторон операторов.

import numbers

class Vector1D:
  def __init__(self, x):
    self.x = x
  def __repr__(self, x):
    return "Vector1D({})".format(self.x)

  def __mul__(self, other):
    if isinstance(other, numbers.Number):
      return self.__class__(self.x * other)
    return NotImplemented

  def __rmul__(self, other):
    # x * vec1d == vec1d * x
    return self.__mul__(other)

  def __rtruediv__(self, other):
    # You can't divide things by a Vector1D
    return NotImplemented

vec2 = Vector1D(2)

vec2 * 3
# Runs vec2.__mul__(2), gets Vector1D(6)

3 * vec2
# First tries int.__mul__(3, vec2), gets NotImplemented
# Then tries Vector1D.__rmul__(vec2, 3), gets Vector1D(6)

3 / vec2
# First tries int.__truediv__(3, vec2), gets NotImplemented
# Then tries Vector1D.__rtruediv__(vec2, 3), gets NotImplemented
# Python raises TypeError
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...