01 浅拷贝
首先来说浅拷贝, 是指拷贝了引用, 但是并没有拷贝内容。
>>> a = [1, 2, 3, 4]
>>> b = a
>>> id(a)
139876864002248
>>> id(b)
139876864002248
可以看到, 再给b 赋值为 a 的值时, 并不是为b单独分了一块内存,然后将内容拷贝进去,
而是将b 指向了a 所在的地址, 这就是浅拷贝。
2 深拷贝
ok, 那么推理而来, 深拷贝就应当是 为变量分配一块内存, 然后将数值拷贝进去,
而不仅仅是只拷贝一个引用。
首先我们先来看深拷贝如何实现:
可以看到, 我们需要引入一个 copy模块, 然后使用copy.deepcopy的方法来实现深拷贝。
结果也就是像下面表述的那样, 不再是给c 一个 a 的引用了 ,分配内存,然后赋具体值。
下面我们再从侧面来验证一下,
# 这里,b是浅拷贝,c是深拷贝
import copy
a = [1, 2, 3, 4]
b = a
c = copy.deepcopy(a)
# 接下来我们改变 a 的值, 并输出a,b,c三个结果
a.append(5)
---------- output --------
a is [1, 2, 3, 4, 5]
b is [1, 2, 3, 4, 5]
c is [1, 2, 3, 4]
可以看到, 在a 发生改变后, 由于b 指向的内存也是 a , 所以b的值也会随之改变。
但是 c 是拷贝了 a 之前的全部内容,这里在a 发生改变之后,并不会影响到 c 。
3 . 进阶
如果我们有变量 c , 且 c = [a , b] ,那么 c 是深拷贝还是浅拷贝呢?
——当然, 根据我们上面所描述的,这里的c是属于浅拷贝, 也就是他的这片内存里不是确切的值,
而是关于 a 和 b 这两个变量的引用。
如果我们再执行 d=c ,还是浅拷贝无疑
但是如果我是这样定义的,
e = copy.deepcopy(c)
那么这可就不是浅拷贝了, 我们可以从下图中验证到这一点
好了, 那么我们思考一下, 这个 e 中到底存的是什么呢?
按照我们上面所说的, 深拷贝这种操作拷贝的是c 中的具体内容, 但是 c中的具体内容就是一个关于 a 和 b 的引用,
那么是不是将这些个引用拷贝进来??? 还是为e 分配一块内存,然后赋值???
这两种情况的表述如下:
OK , 我们来验证一下, 如果e 是拷贝的c 中的引用, 那么如果我们修改 a ,c 也会发生变化, 进而会影响到e ;
但是如果不是拷贝的引用, 那么 a 的修改会影响到c ,但是却不会影响到 e 。
可以看到, 我们的e 不发生变化, 也就是第二种说法才是对的。
即, 在执行深拷贝的时候, 如果发现要拷贝的是一个引用, 那么程序会继续向上挖掘, 知道拷贝到内容为止;
PS: 这可能也就是深拷贝之所以叫做深拷贝的原因所在了吧 ?