перегрузка расширенных арифметических заданий в python - PullRequest
7 голосов
/ 15 февраля 2010

Я новичок в Python, поэтому заранее извиняюсь, если это глупый вопрос.

Для назначения мне нужно перегрузить расширенные арифметические назначения (+ =, - =, / =, * =, ** =,% =) для класса myInt. Я проверил документацию по Python, и вот что я придумал:

def __iadd__(self, other):

    if isinstance(other, myInt):
        self.a += other.a
    elif type(other) == int:
        self.a += other
    else:
        raise Exception("invalid argument")

self.a и other.a ссылаются на int, хранящийся в каждом экземпляре класса. Я попытался проверить это следующим образом, но каждый раз я получаю «Нет» вместо ожидаемого значения 5:

c = myInt(2)
b = myInt(3)
c += b
print c

Может кто-нибудь сказать мне, почему это происходит? Заранее спасибо.

Ответы [ 3 ]

14 голосов
/ 15 февраля 2010

Вам необходимо добавить return self к вашему методу. Объяснение:

Семантика a += b, когда type(a) имеет специальный метод __iadd__, определяется как:

  a = a.__iadd__(b)

, поэтому, если __iadd__ возвращает что-то отличное от self, это то, что будет связано с именем a после операции. Пропустив оператор return, вы опубликовали метод, эквивалентный методу return None.

7 голосов
/ 15 февраля 2010

Расширенные операторы в Python должны возвращать конечное значение, которое будет присвоено имени, к которому они обращаются, обычно (и в вашем случае) self. Как и во всех методах Python, отсутствие оператора return означает возврат None.

Кроме того,

  • Никогда не поднимайте Exception, что невозможно поймать разумно. Код для этого должен был бы сказать except Exception, который перехватит все исключения. В этом случае вы хотите ValueError или TypeError.
  • Не проверяйте тип с помощью type(foo) == SomeType. В этом (и практически во всех) случаях isinstance работает лучше или, по крайней мере, одинаково.
  • Всякий раз, когда вы создаете свой собственный тип, например myInt, вы должны называть его заглавными буквами, чтобы люди могли распознать его как имя класса.
1 голос
/ 15 февраля 2010

Да, вам нужно «вернуть себя», это будет выглядеть так:

def __iadd__(self, other):
    if isinstance(other, myInt):
        self.a += other.a
        return self
    elif type(other) == int:
        self.a += other
        return self
    else:
        raise Exception("invalid argument")
...