为包含列表的对象重载__iadd __()

时间:2019-03-01 18:01:16

标签: python python-2.7 operator-overloading

下面是一个用于保存列表的类,并将提供给它的任何新值添加到列表中(以及能够打印列表):

class foobar:
    def __init__(self, value=None):
        if type(value) is str:
            self.value = [value]
        else:
            self.value = ['']

    def __iadd__(self, new_value):
        self.value.append(new_value)

    def add(self, new_value):
        self.value.append(new_value)

    def __str__(self):
        return str(self.value)

功能 add 仅用于测试目的。

出现的这个问题是对象add__iadd__()的两个功能的行为不同。或者我以为...

实际上,上面提到的两个函数会产生相同的结果,但是add+=会产生不同的结果。

示例运行:

>>> testStr = foobar()
>>> testStr
<__main__.foobar instance at 0x00000000034CCE48>
>>> print testStr
['']
>>> testStr.add('val1')
>>> testStr
<__main__.foobar instance at 0x00000000034CCE48>
>>> print testStr
['', 'val1']
>>> testStr.__iadd__('val2')
>>> testStr
<__main__.foobar instance at 0x00000000034CCE48>
>>> print testStr
['', 'val1', 'val2']
>>> testStr += 'val3'
>>> testStr
>>> print testStr
None

如您所见,+=操作将testStr的{​​{1}}实例转换为foobar,从而(显然)删除其中包含的值。

据我了解,NoneType__iadd__()运算符的行为应相同,但事实并非如此。可以在这里实现+=来适当更新__iadd__()的行为,还是这种类型的操作有问题?

1 个答案:

答案 0 :(得分:1)

__iadd__必须返回更新的对象(可以是self):

def __iadd__(self, new_value):
    self.value.append(new_value)
    return self

您没有返回任何内容,因此使用了None(默认返回值)。

来自__iadd__ documentation

  

这些方法应尝试就地进行操作(修改 self 并返回结果(可以但不一定是自我)。 [...] 例如,如果x是具有__iadd__()方法的类的实例,则 x += y等效于{{1 }}

强调粗体;请注意x = x.__iadd__(y)的等效项。