ida*_*hmu 37 python tuples list
所以我有这个代码:
tup = ([1,2,3],[7,8,9])
tup[0] += (4,5,6)
Run Code Online (Sandbox Code Playgroud)
这会产生此错误:
TypeError: 'tuple' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)
虽然这段代码:
tup = ([1,2,3],[7,8,9])
try:
tup[0] += (4,5,6)
except TypeError:
print tup
Run Code Online (Sandbox Code Playgroud)
打印这个:
([1, 2, 3, 4, 5, 6], [7, 8, 9])
Run Code Online (Sandbox Code Playgroud)
这种行为有望吗?
我意识到这不是一个非常常见的用例.但是,虽然预计会出现错误,但我没想到列表会发生变化.
Joe*_*Joe 35
是的,这是预期的.
元组不能改变.像列表一样的元组是指向其他对象的结构.它并不关心那些物体是什么.它们可以是字符串,数字,元组,列表或其他对象.
因此,对元组中包含的一个对象执行任何操作,包括如果它是列表,则附加到该对象,与元组的语义无关.
(想象一下,如果你写了一个类,它上面有导致其内部状态改变的方法.你不会指望根据它存储的位置调用这些方法是不可能的).
或者另一个例子:
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> t = (l1, l2)
>>> l3 = [l1, l2]
>>> l3[1].append(7)
Run Code Online (Sandbox Code Playgroud)
由列表和元组引用的两个可变列表.我应该能够做最后一行(回答:是).如果您认为答案是否定的,为什么不呢?应该t改变l3(答案:否)的语义.
如果你想要一个连续结构的不可变对象,那么它应该是元组一直向下.
此示例使用中缀运算符:
许多操作都有"就地"版本.与通常的语法相比,以下函数提供了对原位运算符的更原始的访问; 例如,语句x + = y等于x = operator.iadd(x,y).另一种说法是说z = operator.iadd(x,y)相当于复合语句z = x; z + = y.
https://docs.python.org/2/library/operator.html
所以这:
l = [1, 2, 3]
tup = (l,)
tup[0] += (4,5,6)
Run Code Online (Sandbox Code Playgroud)
相当于:
l = [1, 2, 3]
tup = (l,)
x = tup[0]
x = x.__iadd__([4, 5, 6]) # like extend, but returns x instead of None
tup[0] = x
Run Code Online (Sandbox Code Playgroud)
该__iadd__行成功,并修改第一个列表.所以列表已经改变了.该__iadd__调用返回变异列表.
第二行尝试将列表分配回元组,这会失败.
因此,在程序结束时,列表已被扩展,但操作的第二部分+=失败.有关细节,请参阅此问题.
Jun*_*sor 12
嗯,我想这tup[0] += (4, 5, 6)被翻译成:
tup[0] = tup[0].__iadd__((4,5,6))
Run Code Online (Sandbox Code Playgroud)
tup[0].__iadd__((4,5,6))通常在第一个元素中更改列表.但由于元组是不可变的,因此赋值失败.
元组不能直接改变,正确.但是,您可以通过引用更改元组的元素.喜欢:
>>> tup = ([1,2,3],[7,8,9])
>>> l = tup[0]
>>> l += (4,5,6)
>>> tup
([1, 2, 3, 4, 5, 6], [7, 8, 9])
Run Code Online (Sandbox Code Playgroud)