1

我们知道 Python 元组是不可变的,很好。当我尝试更改元组组件的引用时,我得到了一个异常,正如预期的那样。出乎意料的是,无论异常如何,组件都会发生变化,而我认为元组不变性保证了对象不会是可变的。

它是错误、功能还是 PEP?

In [6]: x=([1],)
In [7]: type(x)
Out[7]: tuple
In [8]: x[0]+=[2,3]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-a73186f99454> in <module>()
----> 1 x[0]+=[2,3]

TypeError: 'tuple' object does not support item assignment   
In [9]: x
Out[9]: ([1, 2, 3],)
4

2 回答 2

3

这里更简单:

tup = ([],[])
tup[0].append(0)
tup[1].append(1)
print tup

打印出来

([0],[1])

元组不变性意味着组成元组的对象不能更改为不同的对象。这并不意味着您不能修改它们的值。

现在,话虽如此,您发现了一个非常有趣(如果是这个词)的极端案例,它基本上可以转换为:

x = tup[0]
x += [2,3]
tup[0] = x

所以,前两行按预期工作,然后你得到一个异常。

于 2013-04-26T07:38:45.657 回答
1

有趣的一点。

它表现得像这样的原因是

x[0]+=[2,3]

翻译成

x[0] = x[0].__iadd__([2,3])

这意味着它首先调用__iadd__,它会修改列表,然后才尝试对元组执行非法分配。

(当然,解决方法很容易(例如@luispedro 的回答),但我知道您的问题不是关于如何解决它。)

它是错误、功能还是 PEP?

很难说。由于最小惊讶原则,我倾向于投票给“错误”。人们会期望x[0].extend(y)表现得像a=x[0]; a.extend(y)表现得像a=x[0]; a+=y表现得像x[0]+=y

可能需要一个可能的修复(至少对于 python 内置类型)__setitem__(self, k, v)应该转换为 no-op in case self[k] is v__setitem__(并且应该服从覆盖的自定义类)。

于 2013-04-26T07:39:49.293 回答