我是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
的值也改变了?
我是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
的值也改变了?
该元组是不可变的,但元组内的列表是可变的。你改变了L1(列表),而不是元组。元组包含L1的两个副本,所以它们都显示更改,因为它们实际上是同一个列表。
如果一个对象是“不可变的”,这并不意味着它触及的所有东西都是不可变的。您可以将可变对象放入不可变对象内,并且这不会阻止您继续对可变对象进行变异。
该元组没有得到修改,它仍然包含相同的重复引用列表你给它。
你修改的列表(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])
希望这有帮助。
元组包含两个引用,每个引用都是相同的列表(不是列表的副本,正如您所预料的那样)。因此,列表中的更改仍然会显示在元组中(因为元组只包含引用),但是元组本身没有被更改。因此,不可侵犯性不受侵犯。
如果我写L1 = [1,2,3] A = L1 [1] L1 [1] = 5 打印A – Rachaely
@ user1641021:在该片段中,首先制作一个列表并将其命名为L1。然后,将名称A绑定到L1 [1]所涉及的对象,该对象是整数2.然后将L1的第二个元素更改为5,然后打印A,它仍然是2;你“指出”在整数2,而不是“L1的第二个元素”。 – DSM
但是,如果我写L1 = [1,2,3] A = L1 [1] L1 [1] = 5 打印A结果将是2而不是5.是否因为'L1 [1]'包含L1的副本,而不是L1的参考,这样即使L1改变了它的值,L1 [1]也不会? – Rachaely
从Python文档(http://docs.python.org/reference/datamodel.html),请注意:
不可变容器对象,它包含了一个可变 对象的引用的值当后者的价值改变时可以改变;然而容器 仍然被认为是不可变的,因为它所包含的对象集合不能被 改变。因此,不变性与具有不变的价值并不完全相同,它更加微妙。
你说得对,元组是不可改变的:L2是两个引用的不可变元组L1(不,因为它可能会首先出现,两个列表的元组),而L1并不是一成不变的。当你改变L1时,你不会改变L2,只是L2引用的对象。
使用deepcopy的代替=
:
从拷贝导入deepcopy的
L2 = deepcopy的(L1)
元组是不可变的手段只有一两件事 - 一旦你构造一个元组,不可能修改它。另一方面,列表可以添加元素,从中删除元素。但是,元组和列表都与它们包含的元素有关,但与这些元素的内容无关。
在Python中,这与元组或列表无关,当你添加一个简单的值,比如一个int值时,它被表示为is,但是像列表,元组或其他任何类的复杂值类型的对象是总是存储为参考。
如果你要你的元组转换为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
。
这使得看起来'int'不是'通过引用存储'的方式与“复数值”相同,而是“表示为”。但是'int'与'tuple'完全相同。 – DSM
看起来像你创建一个视图,而不是一个深层复制? –