为什么__mul __()期望整数参数?

时间:2017-06-04 20:37:27

标签: python python-3.x

我得到了TypeError: 'float' object cannot be interpreted as an integer。似乎__mul__()期待仅整数参数。我没有正确定义吗?

# Running Python 3.6.0
from math import sqrt


class Vector(object):
    def __init__(self, coordinates):
        try:
            self.dimension = len(coordinates)
            if self.dimension < 2 or self.dimension > 3:
                raise ValueError
            self.coordinates = tuple(coordinates)

        except ValueError:
            raise ValueError('Must have at least 2 coordinates and no more than 3. Length = {}'.format(self.dimension))

        except TypeError:
            raise TypeError('The coordinates must be an iterable')

        self.magnitude = sqrt(sum([n ** 2 for n in self.coordinates]))

    # This fails with a type error
    def normalized(self):
        try:
            normalized = self.coordinates.__mul__(1.0 / self.magnitude)
        except ZeroDivisionError:
            raise Exception("Cannot normalize zero vector")
        return normalized

    # This fails with a type error
    # def normalized(self):
    #     try:
    #         normalized = self.coordinates * (1.0 / self.magnitude)
    #     except ZeroDivisionError:
    #         raise Exception("Cannot normalize zero vector")
    #     return normalized

    # This works fine
    # def normalized(self):
    #     try:
    #         normalized = [n / self.magnitude for n in self.coordinates]
    #     except ZeroDivisionError:
    #         raise Exception("Cannot normalize zero vector")
    #     return Vector(normalized)

    def __iter__(self):
        return self.coordinates

    def __mul__(self, scalar):
        # Vector scalar multiplication
        return Vector([e * scalar for e in self.coordinates])

    def __str__(self):
        return 'Vector: {}'.format(self.coordinates)


# Run the test...
if __name__ == "__main__":
    v1 = Vector([1.996, 3.108, -4.554])
    print(v1)
    print(v1.normalized())

修改

既然我明白发生了什么,我想澄清将来可能遇到这种情况的人的答案。

问题在于:

normalized = self.coordinates.__mul__(1.0 / self.magnitude)

为了解释的目的,简化为:

a = b.__mul__(c)

a = b * c

此处b是元组,c是数字,是实数。

在Python中

(1, 2) * 3

结果

(1, 2, 1, 2, 1, 2)

换句话说,应用于元组的*运算符导致该元组的复制N次。

这也意味着我们不能用浮点数乘以元组,这是没有意义的。因此错误:

TypeError: 'float' object cannot be interpreted as an integer

有道理。

我的错误在于我将元组乘以self.magnitude而不是将Vector对象乘以self.magnitude,如下所示:

normalized = self.__mul__(1.0 / self.magnitude)

鉴于我对__mul__()的定义,这是有道理的,并且工作正常。这也有效:

normalized = self * (1.0 / self.magnitude)

2 个答案:

答案 0 :(得分:2)

__mul__ applied to a tuple(就像你的坐标一样)重复元组的内容以增加它的长度,因此只有整数才有意义。

您正在尝试将数组的eavh元素乘以数字。如果使ROOT_URL=https://example2.com DDP_DEFAULT_CONNECTION_URL=https://example1.com MONGO_URL=mongodb://mongo.example1.com:27000 为numpy数组,则乘法运算符将正确执行此操作。如果你想将coordinates作为一个元组,那么你需要迭代它来单独乘以每个元素(例如你在为你的矢量类定义的coordinates函数中)。

就个人而言,如果可能的话,我建议使用numpy数组 - 如果使用得当,它们会使你做的很多数学更快更容易。

答案 1 :(得分:2)

您正在将__mul__应用于元组 coordinates。返回n份,显然需要一个整数。

由于您编写了__mul__函数,因此您可能需要调用

normalized = self.__mul__(1.0 / self.magnitude)

或直接

normalized = Vector([e * 1.0 / self.magnitude for e in self.coordinates])