鱼C论坛

 找回密码
 立即注册
查看: 1484|回复: 7

[已解决]这个深度复制和浅度复制还是没能理解

[复制链接]
发表于 2021-2-5 14:20:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
看不懂这个代码的运行结果
例一:
old = [3, 2, 8, 4, 5]
new = old
old = [6]
print(new)
会打印:[3, 2, 8, 4, 5]

例二:
old = [3, 2, 8, 4, 5]
new = old
old = old.sort()
print(new)

会打印[2, 3, 4, 5, 8]

从这个结果可以看出 例一 是深度复制,例二是浅度复制 。可是看过程我没法看出区别,为什么结果会变化呢,例一是把old直接赋值为列表[6],例二是给里列表内容进行排序然后把结果赋值给old,同样是赋值为什么运行结果会不同呢,看了小甲鱼老师的图讲还是不懂。
最佳答案
2021-2-5 14:55:30


善用论坛的搜索功能哈~

【已解决】old  new  列表  id 问题
https://fishc.com.cn/thread-185134-1-1.html

另外,我们看看下面的例子,能不能理解:

这里我们用Python内置函数 id() 来查看他们的内存地址是否相同,相同说明是同一个数据
import copy

l = [[1,2,3],1,2,3]
x = copy.copy(l)     # 浅拷贝:这里相当于列表切片[:]
z = copy.deepcopy(l)  # 深拷贝
print('   原列表id地址:',id(l),'\n浅拷贝列表id地址:',id(x),'\n深拷贝列表id地址:',id(z))

运行结果:
   原列表内元素id地址: 1708146868416 
浅拷贝列表内元素id地址: 1708149001152 
深拷贝列表内元素id地址: 1708149000448
三个列表的 id 全部不相同,说明浅拷贝是直接创建了新的列表,那列表内的元素呢?我们接下来看看下面的运行情况:
import copy

l = [[1,2,3],1,2,3]
x = copy.copy(l)     # 浅拷贝:这里相当于列表切片[:]
z = copy.deepcopy(l)  # 深拷贝
print('   原列表内元素id地址:',id(l[0]),'\n浅拷贝列表内元素id地址:',id(x[0]),'\n深拷贝列表内元素id地址:',id(z[0]))

运行结果:
   原列表内元素id地址: 2351807077120 
浅拷贝列表内元素id地址: 2351807077120 
深拷贝列表内元素id地址: 2351808203584

会发现浅拷贝的元素id和原来列表id相同,所以浅拷贝没有列表内的元素进行拷贝

深拷贝的元素id与原先列表不同,所以深拷将列表内的元素彻彻底底的进行拷贝了

简单的说,深拷贝就是完完全全的复制一遍,然后直接创建了全新的列表

而浅拷贝只复制了列表的外壳,而内部元素还是没有拷贝成新的~

注意的是:这些拷贝对所有可变类容器的来说都有这种性质,比如:列表、元组、字典、集合


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-5 14:44:01 From FishC Mobile | 显示全部楼层
本帖最后由 _2_ 于 2021-2-5 15:01 编辑

先来看例一,old 是一个列表,如果直接 new = old 的话,那么 old 和 new 都指向同一个列表 [3, 2, 8, 4, 5],后来 old 直接指向一个新的列表 [6],但是 new 还是原来的那个列表,所以 new 就是先前那个列表。
例二,前两步是一样的,不再赘述。old.sort() 会直接改变原列表,而 new 也指向那个排列后的新列表,所以就是原来列表排列之后的结果

例一
Screenshot_20210205_145253_com.termux_edit_140753130222791.jpg

例二
Screenshot_20210205_145918_com.termux_edit_141213051047200.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-5 14:49:16 | 显示全部楼层
用python, java这种有垃圾回收机制的还真不好说啊. 其实例一中的深度复制不是发生在new = old , 而是发生在 old = [6], new = old 依然是浅复制, new = old 执行后, new 和 old 指向同一段内存空间, 操作new/old任一都会引起另一个的变化, 而深度复制就会重新分配内存空间. new 和 old 指向不同的内存空间, 两个对象互不影响
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-5 14:55:30 | 显示全部楼层    本楼为最佳答案   


善用论坛的搜索功能哈~

【已解决】old  new  列表  id 问题
https://fishc.com.cn/thread-185134-1-1.html

另外,我们看看下面的例子,能不能理解:

这里我们用Python内置函数 id() 来查看他们的内存地址是否相同,相同说明是同一个数据
import copy

l = [[1,2,3],1,2,3]
x = copy.copy(l)     # 浅拷贝:这里相当于列表切片[:]
z = copy.deepcopy(l)  # 深拷贝
print('   原列表id地址:',id(l),'\n浅拷贝列表id地址:',id(x),'\n深拷贝列表id地址:',id(z))

运行结果:
   原列表内元素id地址: 1708146868416 
浅拷贝列表内元素id地址: 1708149001152 
深拷贝列表内元素id地址: 1708149000448
三个列表的 id 全部不相同,说明浅拷贝是直接创建了新的列表,那列表内的元素呢?我们接下来看看下面的运行情况:
import copy

l = [[1,2,3],1,2,3]
x = copy.copy(l)     # 浅拷贝:这里相当于列表切片[:]
z = copy.deepcopy(l)  # 深拷贝
print('   原列表内元素id地址:',id(l[0]),'\n浅拷贝列表内元素id地址:',id(x[0]),'\n深拷贝列表内元素id地址:',id(z[0]))

运行结果:
   原列表内元素id地址: 2351807077120 
浅拷贝列表内元素id地址: 2351807077120 
深拷贝列表内元素id地址: 2351808203584

会发现浅拷贝的元素id和原来列表id相同,所以浅拷贝没有列表内的元素进行拷贝

深拷贝的元素id与原先列表不同,所以深拷将列表内的元素彻彻底底的进行拷贝了

简单的说,深拷贝就是完完全全的复制一遍,然后直接创建了全新的列表

而浅拷贝只复制了列表的外壳,而内部元素还是没有拷贝成新的~

注意的是:这些拷贝对所有可变类容器的来说都有这种性质,比如:列表、元组、字典、集合


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-6 11:01:32 | 显示全部楼层
本帖最后由 °蓝鲤歌蓝 于 2021-2-6 11:03 编辑

1. 先说一下,
从这个结果可以看出 例一 是深度复制,例二是浅度复制 。
我认为是错误的。

2. 要是学过前面的课程,我相信你已经知道在 python 里什么叫 贴标签。
不管是 例1 还是 例2
old = [3, 2, 8, 4, 5]
new = old
两个变量 old和new都 指向 同一个内存地址的同一个值,就像 old 和 new 手里拿着同一个苹果,任何一个咬了一口都会使这个苹果发生改变。
例2 中的
old = old.sort()
就是一个 “咬苹果” 的行为。所以 old 和 new 才会有相同的改变。
而 例1 中的
old = [6]
,是 赋值,赋值 字面理解就是 给你一个值,这里就相当于给了 old 一个新苹果,这个苹果不再是之前那个苹果了,它们将互不影响(可能这个有人认为是深拷贝吧,其实就是重新赋值而已)。

3. 二楼的截图说明的 很清楚,只是他没说到点子上。
你可以看到
new = old

之后, old 和 new 的 id 地址是相同的,两个都指向相同的内存地址,那么其中任何一个改变了这个内存中的值,都会导致另一个指向该内存的值发生变化(两个人拿着同一个苹果)。

4. 真正的 深拷贝 是要和 浅拷贝 相对来说的,你这两个例子中根本就没有浅拷贝,甚至可以说没有拷贝
python 里的 浅拷贝 和 深拷贝 是对 copy 这个标准库来说的,
import copy

a = [1, 2, 3]
b = copy.copy(a)  # 这是浅拷贝

a = [1, 2, 3]
b = copy.deepcopy(a)  # 这是深拷贝
至于
import copy

a = [1, 2, 3]

b = a

c = copy.copy(a)  # 这是浅拷贝

d = copy.deepcopy(a)  # 这是深拷贝
上面三种有什么不同,你可以先百度知乎看一下,要是还不懂可以在这里问我,已经说的比较多了,让你先消化消化。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-6 12:32:25 | 显示全部楼层
Twilight6 发表于 2021-2-5 14:55
善用论坛的搜索功能哈~

【已解决】old  new  列表  id 问题

谢谢懂了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-6 12:33:00 | 显示全部楼层
°蓝鲤歌蓝 发表于 2021-2-6 11:01
1. 先说一下, 我认为是错误的。

2. 要是学过前面的课程,我相信你已经知道在 python 里什么叫 贴标签。 ...

谢谢懂了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-2-6 12:35:14 | 显示全部楼层
kishere 发表于 2021-2-5 14:49
用python, java这种有垃圾回收机制的还真不好说啊. 其实例一中的深度复制不是发生在new = old , 而是发生在 ...

谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-16 13:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表