在Python中,list
和list[:]
有什么区别(如果有的话)?
阅读时,list
是对原始列表的引用,list[:]
则是浅复制该列表。
在赋值时,list
会重新绑定名称,而list[:]
则是替换列表中先前存在的元素。
此外,不要使用list
作为变量名,因为它会遮蔽内置函数。
后者是指对列表的副本的引用,而不是对列表本身的引用。因此,这非常有用。
>>> li = [1,2,3]
>>> li2 = li
>>> li3 = li[:]
>>> li2[0] = 0
>>> li
[0, 2, 3]
>>> li3
[1, 2, 3]
>>> list1 = [1,2,3]
>>> list2 = list1
>>> list3 = list1[:]
>>> list1[0] = 4
>>> list2
[4, 2, 3]
>>> list3
[1, 2, 3]
这里通过改变list1
来改变list2
,但是list3
没有发生变化。
另一个有用的示例是在将不同类型赋给列表和列表 [:] 时。例如,
l = [1,2,3]
a = numpy.array([4,5,6])
l = a
print(l)
array([4, 5, 6])
当,
l = [1,2,3]
a = numpy.array([4,5,6])
l[:] = a
print(l)
结果是一个列表:
[4, 5, 6]
将第一个list
应用于变量将创建对原始列表的引用。第二个list[i]
将创建一个浅拷贝。
例如:
foo = [1,2,3]
bar = foo
foo[0] = 4
现在,bar和foo将会是:
[4,2,3]
但是:
foo = [1,2,3]
bar = foo[:]
foo[0] = 4
结果将会是:
bar == [1,2,3]
foo == [4,2,3]
:
是切片的意思。然而,如果列表元素本身也是列表,即使 list1 = list[:]
也存在问题。例如:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = a[:]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 3], [4, 5, 6], [7, 8, 9]]
这是因为每个复制到b的列表元素本身就是一个列表,而这种列表的复制涉及到与普通的list1 = list2
相同的问题。
我发现最简单的方法是显式地按照以下方式复制每个列表元素:
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b=[[j for j in i] for i in a]
>>> b
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b[0].remove(2)
>>> b
[[1, 3], [4, 5, 6], [7, 8, 9]]
>>> a
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
当然,对于嵌套列表中每增加一个层级,复制代码就会通过额外的内联for
循环进一步加深。
i
可能无法迭代),则会遇到严重问题。如果您有嵌套列表,则应使用copy模块,而不是嵌套for循环,使用b = copy.deepcopy(a)
。 - RoundTower第一个引用指向原始列表。第二个引用指向原始列表的副本。
看一下这个!
>>> a = [1, 2, 3]
>>> b = a
>>> c = a[:]
>>> a == b
True
>>> a is b
True
>>> a == c
True
>>> a is c
False
>>> a.__repr__
<method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
>>> a.__repr__()
'[1, 2, 3]'
>>> b.__repr__
<method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
>>> c.__repr__
<method-wrapper '__repr__' of list object at 0x7f87ad352988>
请注意,变量a和b都指向地址0x7f87a9ba3688,而变量c则指向0x7f87ad352988。
这种差异非常明显。
变量a和b都引用原始列表对象。
而变量c指向的是原始列表的副本,因此它位于不同的位置。