为什么可以扩展/附加到元组中的列表,但不能分配给它?

时间:2016-09-23 10:24:09

标签: python tuples

通过阅读footnote 4this article启发。

考虑以下情况:

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

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module> 
    t[2] += [5,6]
TypeError: 'tuple' object does not support item assignment

元组是不可变的。因此,正如预期的那样,尝试添加到元组内的列表会引发错误。

但是,如果我们检查我们的元组,列表已被添加到!! (我可以想象这会导致非常难以追踪错误)

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

另外,两者都延伸

>>> t[2].extend([7,8])
>>> t
(1, 2, [3, 4, 5, 6, 7, 8])

并附加

>>> t[2].append(9)
>>> t
(1, 2, [3, 4, 5, 6, 7, 8, 9])

在不引发错误的情况下工作。

所以,我的问题是:

  1. 如果元组是不可变的,为什么可以更改元组中的列表?
  2. 为什么第一个示例会引发错误而另外两个不会引发错误?
  3. 在第一个示例中,为什么即使出现错误,元组内的列表也会更改?

1 个答案:

答案 0 :(得分:0)

  

如果元组是不可变的,为什么可以更改元组中的列表?

因为&#34;元组是不可变的&#34;只表示你不能修改元组。从元组引用的列表不是元组的一部分,它不知道&#34;知道&#34;这是一个元组,它没有办法抵制被修改。

  

为什么第一个例子引发错误而另外两个没有?

由于+=的工作原理。它在列表上调用__iadd__然后(因为__iadd__不需要返回原始对象)尝试将结果修改后的对象分配回元组。第一件事成功,第二件事失败了。

也就是说,对于t[2]具有__iadd__函数的情况,t[2] += [5,6]相当于:

t[2] = t[2].__iadd__([5,6])

  

在第一个例子中,为什么即使出现错误,元组内的列表也会改变?

因为这个Python操作没有提供C ++中的内容,所以我们称之为强大的异常保证&#34;。操作的第一部分已经执行,当第二部分失败时,不能(或无论如何不)反转。有关正式版,请参阅Why does a_tuple[i] += [‘item’] raise an exception when the addition works?