python - 附加到元组中定义的列表 - 这是一个错误吗?

标签 python list tuples

所以我有这个代码:

tup = ([1,2,3],[7,8,9])
tup[0] += (4,5,6)

产生此错误:

TypeError: 'tuple' object does not support item assignment

这段代码:

tup = ([1,2,3],[7,8,9])
try:
    tup[0] += (4,5,6)
except TypeError:
    print tup

打印这个:

([1, 2, 3, 4, 5, 6], [7, 8, 9])

这是预期的行为吗?

注意

我意识到这不是一个非常常见的用例。然而,虽然错误是意料之中的,但我没想到列表会发生变化。

最佳答案

是的,这是预期的。

元组不能更改。元组和列表一样,是指向其他对象的结构。它不关心那些对象是什么。它们可以是字符串、数字、元组、列表或其他对象。

因此,对元组中包含的一个对象执行任何操作,包括附加到该对象(如果它是一个列表)与元组的语义无关。

(想象一下,如果您编写了一个类,该类具有导致其内部状态发生变化的方法。您不会期望根据对象的存储位置调用这些方法是不可能的)。

或者另一个例子:

>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> t = (l1, l2)
>>> l3 = [l1, l2]
>>> l3[1].append(7)

由一个列表和一个元组引用的两个可变列表。我应该能够做最后一行吗(答案:是的)。如果你认为答案是否定的,为什么不呢? t 是否应该改变 l3 的语义(答案:否)。

如果你想要一个顺序结构的不可变对象(immutable对象),它应该是元组。

为什么会出错?

此示例使用中缀运算符:

Many operations have an “in-place” version. The following functions provide a more primitive access to in-place operators than the usual syntax does; for example, the statement x += y is equivalent to x = operator.iadd(x, y). Another way to put it is to say that z = operator.iadd(x, y) is equivalent to the compound statement z = x; z += y.

https://docs.python.org/2/library/operator.html

所以这个:

l = [1, 2, 3]
tup = (l,)
tup[0] += (4,5,6)

等价于:

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

__iadd__ 行成功,并修改了第一个列表。所以名单已经改变。 __iadd__ 调用返回变异列表。

第二行尝试将列表分配回元组,但失败了。

因此,在程序结束时,列表已扩展,但 += 操作的第二部分失败。具体见this question .

关于python - 附加到元组中定义的列表 - 这是一个错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29747224/

相关文章:

python - 如何将列表中元组的第 i 个元素映射到另一个列表中的键以形成字典

python - 使用子进程记录命令的打印语句

list - OCaml:删除列表的第一个元素

python - 如何在python中查找列表的序列号(如行号1、2)

java - 使用 astyanax 在 cassandra 中插入列表

python - 计算 X 和 Y 坐标之间的值

python - 使用 Python unittest : how to improve granularity? 进行集成测试

python - 如何将列表分成两个随机部分

python - 强制 pyYAML 持续转储

tuples - 是否可以将一个函数返回的元组传递给另一个函数?