我是Python新手。这是我对列表的一个问题: 据说列表是可变的,元组是不可变的。但是当我写下以下内容时:
L1 = [1, 2, 3]
L2 = (L1, L1)
L1[1] = 5
print L2
结果是
([1, 5, 3], [1, 5, 3])
而不是
([1, 2, 3], [1, 2, 3])
但是L2
是一个元组,而元组是不可变的。为什么当我更改L1
的值时,L2
的值也会更改?
答案 0 :(得分:7)
从Python文档(http://docs.python.org/reference/datamodel.html),请注意:
包含对mutable的引用的不可变容器对象的值 当后者的值改变时,对象可以改变;但容器是 仍然认为是不可变的,因为它包含的对象集合不能 改变了。因此,不变性并不完全与不可改变的相同 价值,它更微妙。
答案 1 :(得分:4)
元组是不可变的,但元组内的列表是可变的。你改变了L1(列表),而不是元组。元组包含两个L1副本,因此它们都显示了变化,因为它们实际上是相同的列表。
如果一个对象是“不可变的”,那么这并不意味着它触及的所有内容也是不可变的。您可以将可变对象放在不可变对象中,这不会阻止您继续改变可变对象。
答案 2 :(得分:4)
元组没有被修改,它仍然包含与你给它的列表相同的重复引用。
您修改了列表(L1
),而不是元组(或者更准确地说,不是参考到列表中)在元组中)。
例如,你不能够做到
L2[1] = 5
因为你正确陈述了元组是不可变的。
因此元组没有被更改,但是元组包含引用的列表被修改(因为两个条目都引用了相同的列表,输出中的两个值都更改为5
)。元组中的值没有改变。
如果您在此上下文中将引用视为“指针”,则可能有所帮助。
编辑(根据OP在下面的评论中提出的问题):
关于参考文献,列表和副本,这些例子可能会有所帮助:
L=range(5)
s = (L, L[:]) # a reference to the original list and a copy
s
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
然后改变L [2]
L[2] = 'a'
给出:
s
([0, 1, 'a', 3, 4], [0, 1, 2, 3, 4]) # copy is not changed
请注意,“2nd”列表没有更改,因为它包含副本。
现在,
L=range(5)
我们正在创建列表的两个副本并提供对元组的引用
s = (L[:], L[:])
now
L[2] = 'a'
除了原始列表L 之外,不会影响任何内容
s
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
希望这有用。
答案 3 :(得分:2)
你是对的,元组是不可变的:L2是两个对L1的引用的不可变元组(不是,因为它可能首先出现,是两个列表的元组),而L1不是不可变的。当您改变L1时,您不会改变L2,只会改变L2引用的对象。
答案 4 :(得分:2)
使用 deepcopy 代替=
:
来自copy import deepcopy
L2 =深度扫描(L1)
答案 5 :(得分:1)
元组包含两个引用,每个引用都在同一个列表中(不是您可能预期的列表副本)。因此,列表中的更改仍将显示在元组中(因为元组仅包含引用),但元组本身不会更改。因此,它的不变性不会受到侵犯。
答案 6 :(得分:0)
元组是不可变的只意味着一件事 - 一旦你构造了一个元组,就不可能修改它。另一方面,列表可以添加元素,从中删除元素。但是,元组和列表都与它们包含的元素有关,但与这些元素的含义无关。
在Python中,这与元组或列表无关,当你添加一个简单的值(如int)时,它会按原样表示,但任何复杂的值如列表,元组或任何其他类 - 类型对象始终存储为参考。
如果你要将你的元组转换为set()
,你会收到一条可能让你感到惊讶的错误信息,但考虑到上述情况,它应该是有道理的:
>>> L=range(5)
>>> s = (L, L[:]) # a reference to the original list and a copy
>>> set(1, 2, s)
>>> set((1, 2, s))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
由于set
的值必须在添加到集合后永远不会更改,因此不可变元组s
中包含的任何可变值都会引发TypeError
。