浅复制和深复制的区别在于,浅复制只复制引用到新的列表中(引用能够理解为地址),不会建立新对象。而深复制建立新的对象,并把对象保存在新的地址中。浅复制和深复制对可变和不可变序列的影响是不同的。对可变序列的浅复制会带来意想不到的结果。看示例1python
示例1 >>>a = [[1],2,3,4] >>>b = list(a) >>>a[0].append(0) >>>a [[1, 0], 2, 3, 4] >>>b [[1, 0], 2, 3, 4]
对于复制列表,最简单的方式是使用内置类型的构造方法list(),也能使用[:]复制副本。无论是构造方法仍是[:]都是浅复制。从示例1能够看到,对a的第0个元素进行了修改,可是b也发生了改变。为何呢?我先要理解a和b之间发生了什么?见下面图1。 app
由于浅复制只是复制了引用到新的列表中,他们的引用仍是同样的,a和b的第0个元素都是指向列表[1],由于列表是可变序列,能够原地修改,因此修改后引用不变。这就致使了a的修改会带来了b的改变。再看看示例2函数
示例2 >>>a = [1,2,3,4] >>>b = list(a) >>>a[0]=0 >>>a [0, 2, 3, 4] >>>b [1, 2, 3, 4]
示例2中a的修改并无带有b的变化,他们之间有发生了什么?看下面图2。 code
由于浅复制的缘由,原本a,b的引用都是同样的,而后对a的第0元素进行了修改,因为该元素是不可变序列,要改变只能从新建立新的对象,因此a的第0个元素的引用发生了改变,但这并不影响到b的第0个元素的引用。好了,再看一个复杂点的例子,看示例3对象
示例3 >>>l1=[1,[2,3,4],(5,6,7)] >>>l2=list(l1) >>>l1.append(10)#1 >>>l1[1].remove(3)#2 >>>l2[1] +=[8,9]#3 >>>l2[2] += (10,11)#4
- l2修改对l2没影响
- l2修改对l2有影响
- l2修改对l1有影响
- l2修改对l1没影响
浅复制的结果可能不是你想要的,那么如何作深复制呢?。事实上,copy模块提供的copy和deepcopy函数能为任意对象作浅复制和深复制,看示例4。blog
示例4 >>>import copy >>>l1=[1,[2,3,4],(5,6,7)] >>>l2=copy.deepcopy(l1) >>>l3=copy.copy(l1) >>>l1[1].remove(3) >>>l1 >>>l1=[1,[2,4],(5,6,7)] >>>l2 >>>l1=[1,[2,3,4],(5,6,7)] >>>l3 [1,[2,4],(5,6,7)]
l2是l1的深复制,l3是l2的浅复制,对l1第1个元素进行了修改,虽然该元素是可变对象,影响了l3,可是没有影响到l2。由于l2是深复制的缘由,因此是建立了新的对象,有了新的引用,能够说是跟l2没有一毛钱关系了,他们只是内容同样而已。最后看一个有趣的现象,看示例5。图片
示例5 >>>l1=[1,[2,3,4],(5,6,7)] >>>l1.append(l1) >>>l1 [1, [2, 4], (5, 6, 7), [...]]
看l2最后的元素竟然是神奇的[...],这到底是什么回事?看看下面图3的引用就知道了,来! rem
能够看到,列表最后元素的引用指向了自身,自身的最有元素仍是指向自身,这是一个无限循环引用,因此出现了[...]class
以上,欢迎指出错误。import
更多精彩文章请关注我公众号:CVpython