3

我想子类化一个不可变类型或实现我自己的一个,其行为类似于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

4 回答 4

15

根本不实施__iadd__,而只是__add__

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

如果没有x.__iadd__,Python 会简单地计算x += yx = x + y doc

于 2012-08-06T22:03:32.860 回答
3

当它看到时i += 1,Python 会尝试调用__iadd__. 如果失败,它将尝试调用__add__.

在这两种情况下,调用的结果都将绑定到名称,即它会尝试i = i.__iadd__(1)然后i = i.__add__(1).

于 2012-08-06T22:05:25.727 回答
2

的返回值__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
于 2012-08-06T22:26:13.283 回答
-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
>>>
于 2012-08-06T22:15:19.077 回答