开发者学堂课程【Python入门 2020年版:深拷贝和浅拷贝的区别】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/639/detail/10307
深拷贝和浅拷贝的区别
内容介绍
一、浅拷贝回顾
二、深拷贝
三、网址推荐
一、浅拷贝回顾
首先我们定义一个 nums,nums1 = nums 为等于时,表示相互关联的操作既不是深复制也不是浅复制,它仅仅是一个指向,是赋值操作。
1.赋值
#浅复制(拷贝)
nums = [1
,2,3,4,5]
nums1 = nums
#深拷贝/浅拷贝?都不是,只是一个赋值
2. 浅复制回顾
(1)使用 Copy 方法
而 nums2 = nums.copy()表示浅复制,两者内容一致,但并不是同一个对象,无论修改其中的任何一个,都不会改变另一个的内容。
代码
nums = [1
,2,3,4,5]
nums2 = nums.copy()
#浅复制。两个内容一模一样,但是不是同一个对象
(2)使用 copy 模块
除此之外还可以使用 copy 模块,nums3 = copy.copy(nums)
来进行浅拷贝,和 nums2 = nums.copy() 两者的效果一致。
代码
import copy
nums = [1
,2,3,4,5]
#浅拷贝,两个内容一模一样,但是不是同一个对象
二、深拷贝
深拷贝与浅拷贝不一样,只能使用 copy 模块实现,同时涉及到列表的嵌套。定义一个 words 列表并在其中添加嵌套。
1.引例
代码
import copy
#深拷贝,只能使用 copy 横块实现
words =[' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
#words1是 words 的浅拷贝
#浅拷贝认为只拷贝了一层
words1 = words.copy()
//把 words 浅复制一份给 words1
words[0] = ‘
你好’
//将 word 中第一个元素变为‘你好’
print(words1)
//输出 words1
words[2][0] = 1
//改变嵌套列表中的元素
print(words1)
//再次输出 words1
输出结果
[ ' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
[ ' hello', 'good ',[1,200,300],'yes', 'hi', 'ok' ]
思路解析:
Words 如今指向一块内存空间,此时又有一个 words1又复制了 words 指向内存空间中的所有元素,同时指向另一个空间。两者是不同的内存地址。此时将 words[0]改为’你好’,word1[0]中的内容不会发生改变。
但如果改变 word 中嵌套的列表中的第一个元素 words[2][2]为1,再次输出浅拷贝生成的 words1,会发现 word1中的对应的元素发生了改变。
因为浅拷贝被认为只拷贝了一层,所以 words 嵌套的内层列表并没有被拷贝,即列表中嵌套的如果是列表元素,不会再被拷贝。而是两者都指向该列表。
将内层列表的第一个元素100改为1时,words1是与 Word 共同指向嵌套部分的列表,所以输出的结果也变为1。
2.深拷贝
深拷贝只可以用 copy 模块来实现,如要对 words 进行深拷贝写法为 words2 = copy.deepcopy(words)。
代码
import copy
#深拷贝,只能使用 copy 横块实现
words = [ ' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
#深拷贝的 words2
words2 = copy.deepcopy(words)
words[0] = ‘
你好’
print(words2)
words[2][0] = 1
print(words2)
输出结果
[ ' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
[ ' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
words2和 word1不同,它是将 word 里全都拷贝过来。不管 word 里有任何嵌套列表都完全复制下来。
如将 words[0]改为’你好’或者是将 word 里嵌套的列表第一个元素进行修改,再输出 word2的结果都可以看出不会有任何的变化。实现了真正的两个独立的空间。
Tip:在元素遍历拿出来依次拷贝也不一定是深拷贝,需要通过遍历深度来判断。
三、网站推荐
同时我们可以登录 pythontutor.com 网站在其中的 Python Tutor 中去查看我们的代码的虚拟运行过程依次判断理解深拷贝。
首先在网站中输入代码,点击虚拟化执行代码。
网址:pythontutor.com
代码
import copy
words = [ ' hello', 'good '
,[100,200,300],'yes', 'hi', 'ok' ]
Word1 = words.copy()
words2 = copy.deepcopy(words)
words[2][0] = 1
虚拟执行过程:
可以看出,words 在指向其中嵌套的列表时,指向的是另一块内存。当执行第三行代码浅复制时,words1里的嵌套列表和 word 指向的是同一块内存,所以当改变嵌套列表元素时,会对应发生改变。
而当执行第四行的深复制代码时,word2中的嵌套列表并没有和 word 指向同一内存地址,而是完整的复制下 word 的内容,再全部指向另一块内存地址。
最后将 words[2][0]即 Word 中嵌套列表的第一个元素变为1,可以看到 words 和浅复制结果 word1指向的数据发生变化,而 words2并没发生变化。