等等,这就是Python浅复制和深复制的区别!

浅复制和深复制的区别在于,浅复制只复制引用到新的列表中(引用能够理解为地址),不会建立新对象。而深复制建立新的对象,并把对象保存在新的地址中。浅复制和深复制对可变和不可变序列的影响是不同的。对可变序列的浅复制会带来意想不到的结果。看示例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。 图1app

由于浅复制只是复制了引用到新的列表中,他们的引用仍是同样的,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。 图2code

由于浅复制的缘由,原本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
  1. l2修改对l2没影响
  2. l2修改对l2有影响
  3. l2修改对l1有影响
  4. 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 在这里插入图片描述

相关文章
相关标签/搜索