列表对象的copy()方法返回列表的浅复制。所谓浅复制,是指生产一个新的列表,并且把原列表中所有元素的引用都复制到新列表中。如果原列表中只包含整数、实数、复数等基本类型或元组、字符串这样的不可变类型,一般是没有问题的。但是,如果原列表中包含列表之类的可变数据类型,由于浅复制时只是把子列表的引用复制到新列表中,这样修改任何一个都会影响另外一个。例如:
>>> x = [1, 2, [3, 4]] #原列表中包含子列表
>>> y = x.copy() #浅复制
>>> x
[1, 2, [3, 4]]
>>> y #两个列表中的内容看起来完全一样
[1, 2, [3, 4]]
>>> y[2].append(5) #为新列表中的子列表追加元素
>>> y
[1, 2, [3, 4, 5]]
>>> x #原列表中的子列表也被修改了
[1, 2, [3, 4, 5]]
>>> x[0] = 6 #整数、实数等不可变类型不受此影响
>>> x
[6, 2, [3, 4, 5]]
>>> y
[1, 2, [3, 4, 5]]
>>> y.append(6) #在新列表尾部追加元素
>>> y
[1, 2, [3, 4, 5], 6]
>>> x #原列表不受影响
[6, 2, [3, 4, 5]]
列表对象的copy()方法和切片操作与标准库copy中的copy()函数一样都是返回浅复制,如果想避免上面代码演示的问题,可以使用标准库copy中的deepcopy()函数实现深复制。所谓深复制,是指对原列表中的元素进行递归,把所有的值都复制到新列表中,对嵌套的子列表不仅仅是复制引用。这样一来,新列表和原列表是互相独立,修改任何一个都不会影响另外一个。
>>> import copy
>>> x = [1, 2, [3, 4]]
>>> y = copy.deepcopy(x) #深复制
>>> y
[1, 2, [3, 4]]
>>> x[2].append(5) #为原列表中的子列表追加元素
>>> x
[1, 2, [3, 4, 5]]
>>> y #新列表中的子列表不受影响
[1, 2, [3, 4]]
>>> y.append(6) #在新列表尾部追加元素
>>> y
[1, 2, [3, 4], 6]
>>> x #原列表不受影响
[1, 2, [3, 4, 5]]
不管是浅复制还是深复制,与列表对象的直接复制都是不一样的情况,这一点是必须注意的。下面的代码把同一个列表赋值给两个不同的变量,这两个变量是互相独立的,修改任何一个都不会影响另外一个。
>>> x = [1, 2, [3, 4]]
>>> y = [1, 2, [3, 4]] #把同一个列表对象赋值给两个变量
>>> x.append(5)
>>> x[2].append(6)
>>> x
[1, 2, [3, 4, 6], 5]
>>> y
[1, 2, [3, 4]]
下面的代码演示的是另外一种情况,把一个列表变量赋值给另外一个变量,这样的话两个变量指向同一个列表对象,对其中一个做的任何修改都会立刻在另外一个变量得到体现。
>>> x = [1, 2, [3, 4]]
>>> y = x #两个变量指向同一个列表
>>> x[2].append(5)
>>> x.append(6)
>>> x[0] = 7
>>> x
[7, 2, [3, 4, 5], 6]
>>> y #对x做的任何修改,y都会得到影响
[7, 2, [3, 4, 5], 6]