2016-08-21 45 views
11

我只是在解释器中忙碌着,碰到一些我不明白的东西。当我创建一个列表作为元素的元组,然后尝试更新列表时,会发生一些奇怪的事情。例如,当我运行此:更新一个元组内的列表

tup = (1,2,3,[4,5]) 
tup[3] += [6] 

我得到:

TypeError: 'tuple' object does not support item assignment 

这正是我的预期。但是后来当我再次引用元组,我得到:

>>> tup 
(1, 2, 3, [4, 5, 6]) 

所以名单,其实是更新尽管蟒蛇抛出异常。这是如何运作的?我无法想象我真的想要做这样的事情,但我仍然想知道发生了什么。谢谢。

回答

27

这实际上记录在Python docs

编辑:这是一个总结,以便这是一个更完整的答案。

  1. 当我们使用+=,Python会自动调用关于该项目的__iadd__魔术方法,然后使用在随后的项目分配的返回值。
  2. 对于列表,__iadd__相当于在列表上调用extend,然后返回列表。
  3. 因此,当我们调用tup[3] += [6],它相当于:

    result = tup[3].__iadd__([6]) 
    tup[3] = result 
    
  4. 从#2,我们可以确定这相当于:

    result = tup[3].extend([6]) 
    tup[3] = result 
    
  5. 第一行呼吁extend成功在列表中,因为列表是可变的,所以它会更新。但是,随后的分配失败,因为元组是不可变的,并引发错误。
+2

我想这个答案会从另一个好处,那就是因为扩展不仅仅是'tup [3] .__ iadd __([6])';它是'tup [3] = tup [3] .__ iadd __([6])''。 'list .__ iadd__'返回它正在变异的同一个对象是很方便的。 – zondo

+0

感谢您的文档链接!这是一个很大的帮助。 –

+0

谢谢,我没有在文档中看到这一点。所以为了确保我理解这个权利,基本上在我的例子中,列表被更新,因为我只是在做tup [3] .__ iadd __([6]),然后python尝试(并失败)元组上的项目分配?所以我得到例外说它失败了,但到那时我们已经更新了列表? –

相关问题