繁体   English   中英

为什么我的代码在包含项目中使用__iadd__时会生成__setitem__错误?

[英]Why does my code generate an __setitem__ error when using __iadd__ in contained item?

谁能告诉我为什么这段代码抱怨容器上没有__setitem__ 我以为我只需要容器上的__getitem__来获取项目,然后__iadd__来设置值,不知道为什么它会期待__setitem__

class Item:
    def __init__(self):
        pass

    def __iadd__(self, value):
        print 'added: ' + value
        return self


class Container:

    def __init__(self):
        self.__items = {
            'foo': Item()
        }

    def __getitem__(self, name):
        return self.__items[name]

if __name__ == '__main__':

    # works!
    con = Container()
    item = con['foo']
    item += 'works!'

    # wtf?
    con['foo'] += "what's going on?"

    # output:

    # added: works!
    # added: what's going on?
    # Traceback (most recent call last):
    #   File "foo.py", line 27, in <module>
    #     con['foo'] += "what's going on?"
    # AttributeError: Container instance has no attribute '__setitem__'

谜语我:会发生什么事,如果你使用+=上一个不变的类型,就像int 你能明白为什么在[]返回的值上调用+=还需要调用__setitem__吗?

真正的诀窍是理解python中有一个=中的任何运算符都涉及一个赋值,因为它需要能够以预期的方式处理不可变类型。

为清楚起见,请考虑以下事项:

>>> a = 10*10**9
>>> b = a
>>> a is b
True
>>> a += 1
>>> a is b
False

显然, a被指定为引用新值。 因此,它认为当您对__getitem__返回的值执行+=时会发生同样的情况。

不幸的是,python文档非常糟糕,说明这将是会发生什么,但正如另一个答案指出的反编译,它显然确实,并且必须正确处理存储在可变容器中的不可变类型。

基本上,

con['foo'] += "what's going on?"

编译成如下:

item = con['foo']
item += "what's going on?"
conf['foo'] = item

你可以看到,反编译代码,如:

  2           0 LOAD_GLOBAL              0 (con)
              3 LOAD_CONST               1 ('foo')
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR       
             10 LOAD_CONST               2 ("what's going on?")
             13 INPLACE_ADD         
             14 ROT_THREE           
             15 STORE_SUBSCR        

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM