在python中分配给一个可变的元组组件:一个bug?一项功能?

时间:2013-04-26 07:35:10

标签: python tuples immutability pep

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

是bug,功能还是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],)

2 个答案:

答案 0 :(得分:3)

这里更简单:

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

打印出来

([0],[1])

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

现在,说了这么多,你发现了一个非常有趣的(如果是这个词)角落案例,它基本上转化为:

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

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

答案 1 :(得分:1)

有趣的一点。

它的行为是这样的

x[0]+=[2,3]

转换为

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

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

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

  

是bug,功能还是PEP?

很难说。由于最小惊讶原则,我倾向于投票给“一个虫子”。可以预期x[0].extend(y)的行为与a=x[0]; a.extend(y)的行为类似a=x[0]; a+=y,表现得像x[0]+=y

可能需要修复(至少对于python内置类型)__setitem__(self, k, v)self[k] is v的情况下应转换为no-op。 (以及覆盖__setitem__的自定义类应遵守)。