【问题标题】:Python operator overloading not workingPython运算符重载不起作用
【发布时间】:2018-07-14 23:30:59
【问题描述】:

我有一个 Vector2 类:

class Vector2():
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector2(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Vector2(self.x - other.x, self.y - other.y)

    def __mul__(self, other):
        return Vector2(self.x * other, self.y * other)

    def __neg__(self):
        return Vector2(-self.x, -self.y)

    def magnitude(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

    @classmethod
    def distance(self, v1, v2):
        return math.sqrt((v2.x - v1.x) ** 2 + (v2.y - v1.y) ** 2)

    def normalize(self):
        return self * (1/self.magnitude())

当我尝试执行 1.0 * Vector2() 时,我收到错误消息: TypeError: *: 'float' 和 'instance' 不支持的操作数类型

但是,有时它会按预期工作:

#this works as intended, s is a float
ball.pos -= ball.vel.normalize() * s

ball.vel 是一个向量,我可以乘以一个浮点数。 在我的代码的许多部分中,向量乘以浮点数而没有错误。

有谁知道这种不一致来自哪里?

谢谢

【问题讨论】:

  • 你确定你是Vector2() * 1.0而不是1.0 * Vector2()
  • 哇,原来如此。为什么这很重要?
  • 因为float * whatever 是由float 定义的,而whatever * float 是由whatever 定义的
  • 有道理,感谢您的快速响应!

标签: python overloading operator-keyword


【解决方案1】:

定义一个__rmul__ 方法以使a_float * a_vector 工作。它可以很简单

def __rmul__(self, other):
    return self * other

其他运算符也有a dunder-r version。当没有为给定类型定义正常版本时,将调用这些反射运算符。请参阅NotImplemented 内置常量的文档。

表达式a * b 等价于a.__mul__(b),除非ba 类的子类的实例,或者a.__mul__(b) 返回NotImplemented,在这种情况下它是b.__rmul__(a)

【讨论】:

  • 更简单:__rmul__ = __mul__。显然,这只适用于交换运算符。
  • @dan04 好点,但是如果子类覆盖__mul__ 怎么办?那么__rmul__ 仍然会使用旧版本!
  • @gilch:如果子类覆盖__mul__ 而不是__rmul__,那是子类的错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
相关资源
最近更新 更多