Как реализовать "__iadd__()" для неизменяемого типа?

Я хотел бы создать подкласс неизменяемого типа или реализовать свой собственный, который ведет себя как int делает, как показано в следующем сеансе консоли:

>>> i=42
>>> id(i)
10021708
>>> i.__iadd__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__iadd__'
>>> i += 1
>>> i
43
>>> id(i)
10021696

Не удивительно, int объекты не имеют __iadd__() метод, но применяя += к одному не приводит к ошибке, вместо этого, по-видимому, создает новый int а также каким-то волшебным образом переназначает его на имя, указанное в расширенном операторе присваивания.

Можно ли создать пользовательский класс или подкласс встроенного неизменяемого класса, который делает это, и если да, то как?

4 ответа

Решение

Возвращаемое значение __iadd__() используется. Вам не нужно возвращать объект, к которому добавляется; Вы можете создать новый и вернуть его. На самом деле, если объект неизменен, вы должны.

import os.path

class Path(str):
    def __iadd__(self, other):
        return Path(os.path.join(str(self), str(other)))

path = Path("C:\\")
path += "windows"

print path

Просто не реализуй __iadd__, но только __add__:

>>> class X(object):
...     def __add__(self, o):
...             return "added"
>>> x = X()
>>> x += 2
>>> x
'added'

Если нет x.__iadd__Питон просто вычисляет x += y как x = x + y док.

Когда он видит i += 1Пифон попробует позвонить __iadd__, Если это не удастся, он попытается позвонить __add__,

В обоих случаях результат вызова будет привязан к имени, т.е. i = i.__iadd__(1) а потом i = i.__add__(1),

class aug_int:
    def __init__(self, value):
        self.value = value

    def __iadd__(self, other):
        self.value += other
        return self

>>> i = aug_int(34)
>>> i
<__main__.aug_int instance at 0x02368E68>
>>> i.value
34
>>> i += 55
>>> i
<__main__.aug_int instance at 0x02368E68>
>>> i.value
89
>>>
Другие вопросы по тегам