我们知道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],)
答案 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__
的自定义类应遵守)。