Python integer * float = NotImplemented - PullRequest
0 голосов
/ 16 июля 2011

Так что я возился с написанием векторного класса, когда обнаружил этот интересный факт.

>>> e = int(3)
>>> e.__mul__(3.0)
NotImplemented

Может кто-нибудь объяснить, почему это так и как впоследствии исправить мой векторный класс?

class Vector(tuple):
    '''A vector representation.'''
    def __init__(self, iterable):
        super(Vector, self).__init__(iterable)

    def __add__(self, other):
        return Vector(map(operator.add, self, other))

    def __sub__(self, other):
        return Vector(map(operator.sub, self, other))

    def __mul__(self, scalar):
        return Vector(map(scalar.__mul__, self))

    def __rmul__(self, scalar):
         return Vector(map(scalar.__mul__, self))

    def __div__(self, scalar):
        return Vector(map(scalar.__rdiv__, self))

РЕДАКТИРОВАТЬ: Чтобы быть немного более ясным:

>>> a = Vector([10, 20])
>>> a
(10, 20)
>>> b = a / 2.0
>>> b
(5.0, 10.0)
>>> 2 * b
(NotImplemented, NotImplemented)

1 Ответ

11 голосов
/ 16 июля 2011

Это потому, что когда вы делаете 3 * 3.0, интерпретатор вызывает (3.0).__rmul__(3) после того, как осознает, что (3).__mul__(3.0) не реализован

Функции __mul__ и __rmul__ с плавающей точкой приводят к целым числам с плавающей точкой, но это должноне случится с классом int.

В противном случае 3 * 3.5 будет 9 вместо 10.5

Второй вопрос:

Почемулюди настаивают на map, когда понимание списка (и выражения генератора) намного лучше?

попробуйте это:

def __mul__(self, scalar):
    return Vector(scalar * j for j in self)

Вы должны сделать это для любой другой функции в классе.

...