鱼C论坛

 找回密码
 立即注册
查看: 1071|回复: 19

[已解决]浅拷贝和深拷贝

[复制链接]
发表于 2020-6-21 16:20:18 | 显示全部楼层 |阅读模式

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

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

x
从网上搜了一部分,但还是没理解,主要想搞明白 b拷贝的a,什么情况下一方改变两者都改变,什么时候只改变自身?
再就是赋值操作, 直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变 这是网上的解释,
然后我尝试 a=6 ,b=a ,然后 a=7,b却没有发生改变 还是6,这不是矛盾吗?
求大神指教
最佳答案
2020-6-21 17:23:15
今天的我更强了 发表于 2020-6-21 17:19
所以说
list1=[1,2]
list2=[3,4]

容器类型都是一样的 不管是字典 还是 列表,浅拷贝对容器来说是重新创建了一个新容器,但是对容器内的元素来说并没有

容器互不影响,但是当时的浅拷贝时候的可变元素会相互影响,不可变元素是不会的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-6-21 16:21:13 | 显示全部楼层
本帖最后由 xiaosi4081 于 2020-6-21 16:34 编辑

列表才是这样的:
>>> b = ["a"]
>>> a = b
>>> a.append("t")
>>> b
['a', 't']
>>> 
因为普通赋值是把1号变量存储进一个新的变量里
列表只是一个指针
所以面a只是复制了b的地址
而:
>>> c = b.copy()
>>> c.append("e")
>>> c
['a', 't', 'e']
>>> b
['a', 't']
就是把b的内容复制到c

PS:不妨去看看c语言的数组


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

使用道具 举报

发表于 2020-6-21 16:27:43 | 显示全部楼层
然后我尝试 a=6 ,b=a ,然后 a=7,b却没有发生改变 还是6,这不是矛盾吗?


你可以这样理解,把变量名当成数值的别名,你这里的赋值 a = 6 只是把 6 这个数值取了个 a 的外号

a 是指向 6 的 ,而 b = a 实际上还是为 6 取了第二个别名 b ,所以此时 6 有两个别名 a,b

当你 a=7 ,时候 就把这个别名给了 7 , 而 b 这个别名还是 6 的 ,所以就不会发生改变
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:31:12 | 显示全部楼层
深拷贝需要导入copy 模块来调用
import copy
x = [xxxx]
y = copy.deepcopy(x)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-21 16:36:33 | 显示全部楼层
xiaosi4081 发表于 2020-6-21 16:21
列表才是这样的:

因为普通赋值是把1号变量存储进一个新的变量里

list1=[1,2]
list2=[3,4]
dict1={'1':list1,'2':list2}
dict2=dict1.copy()
dict1['1'][0]=5
result=dict1['1'][0]+dict2['1'][0]
print(result)
print(dict2)

这个为什么会同时发生改变呢? 这和第二个例子不一样吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:38:34 | 显示全部楼层
本帖最后由 Stubborn 于 2020-6-21 16:43 编辑

理解一下,纸片(不可变类型数据),和纸盒(可变类型数据)的区别

当指针改变了指向,指向新的“纸片”‘纸盒’,才会发生具体的改变。

https://fishc.com.cn/thread-171936-1-1.html

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

使用道具 举报

 楼主| 发表于 2020-6-21 16:39:09 | 显示全部楼层
Twilight6 发表于 2020-6-21 16:31
深拷贝需要导入copy 模块来调用

list1=[1,2]
list2=[3,4]
dict1={'1':list1,'2':list2}
dict2=dict1.copy()
dict1['1'][0]=5
result=dict1['1'][0]+dict2['1'][0]
print(result)
print(dict2)
和下面这串代码
>>> c = b.copy()
>>> c.append("e")
>>> c
['a', 't', 'e']
>>> b
['a', 't']
都是用了.copy()
为什么一个会影响 一个不会呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:43:34 | 显示全部楼层
本帖最后由 Twilight6 于 2020-6-21 18:17 编辑

举些例子吧,先看看这两拷贝的区别:

这里我们用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
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:45:43 | 显示全部楼层
Twilight6 发表于 2020-6-21 16:43
举些例子吧,先看看这两拷贝的区别:

这里我们用Python内置函数 id() 来查看他们的内存地址是否相同,相 ...

列表的  [:]  会返回一个新的列表,可不是‘浅拷贝哦’
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:46:20 | 显示全部楼层
Stubborn 发表于 2020-6-21 16:45
列表的  [:]  会返回一个新的列表,可不是‘浅拷贝哦’

浅拷贝也是返回新列表啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 16:51:33 | 显示全部楼层
Stubborn 发表于 2020-6-21 16:45
列表的  [:]  会返回一个新的列表,可不是‘浅拷贝哦’

对列表进行[:] 操作 就可以等价对列表进行浅拷贝,这点我敢肯定我没错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-21 17:19:08 | 显示全部楼层
Twilight6 发表于 2020-6-21 16:43
举些例子吧,先看看这两拷贝的区别:

这里我们用Python内置函数 id() 来查看他们的内存地址是否相同,相 ...

所以说
list1=[1,2]
list2=[3,4]
dict1={'1':list1,'2':list2}
dict2=dict1.copy()
dict1['1'][0]=5
result=dict1['1'][0]+dict2['1'][0]
print(result)
print(dict2)
这个字典是内部子元素发生改变,会影响另外一方

c = b.copy()
>>> c.append("e")
>>> c
['a', 't', 'e']
>>> b
['a', 't']
这一个是表层的改变 不会相互影响 是这样么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-21 17:19:42 | 显示全部楼层
Twilight6 发表于 2020-6-21 16:51
对列表进行[:] 操作 就可以等价对列表进行浅拷贝,这点我敢肯定我没错

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

使用道具 举报

 楼主| 发表于 2020-6-21 17:19:43 | 显示全部楼层
Stubborn 发表于 2020-6-21 16:38
理解一下,纸片(不可变类型数据),和纸盒(可变类型数据)的区别

当指针改变了指向,指向新的“纸片” ...

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

使用道具 举报

发表于 2020-6-21 17:23:15 | 显示全部楼层    本楼为最佳答案   
今天的我更强了 发表于 2020-6-21 17:19
所以说
list1=[1,2]
list2=[3,4]

容器类型都是一样的 不管是字典 还是 列表,浅拷贝对容器来说是重新创建了一个新容器,但是对容器内的元素来说并没有

容器互不影响,但是当时的浅拷贝时候的可变元素会相互影响,不可变元素是不会的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-21 17:23:55 | 显示全部楼层
Twilight6 发表于 2020-6-21 17:23
容器类型都是一样的 不管是字典 还是 列表,浅拷贝对容器来说是重新创建了一个新容器,但是对容器内的元 ...

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

使用道具 举报

发表于 2020-6-21 17:25:19 | 显示全部楼层


你应该设置我之前又长又粗的那个为最佳 我好不容易感觉写的好好哈哈哈哈哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-21 17:28:17 | 显示全部楼层
Twilight6 发表于 2020-6-21 17:25
你应该设置我之前又长又粗的那个为最佳  我好不容易感觉写的好好哈哈哈哈哈

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

使用道具 举报

发表于 2020-6-21 17:28:44 | 显示全部楼层

没事 我和你开玩笑哪~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-21 17:29:42 | 显示全部楼层
Twilight6 发表于 2020-6-21 17:28
没事 我和你开玩笑哪~~~

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-20 11:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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