python深拷贝浅拷贝如何理解

本文通过示例详细解释了Python中可变对象(如列表)和不可变对象(如整数)的区别,以及在深拷贝和浅拷贝操作下,如何影响对象的内存地址和值的变化。重点讨论了列表作为可变对象在拷贝过程中的行为,以及如何使用`copy()`和`deepcopy()`函数确保拷贝的独立性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开始我们要先了解可变对象不可变对象,所谓的可变对象就是即使我们对对象的值进行修改对象所指向的地址不会改变,由此类推,不可变对象就是一旦我们对对象的值进行修改对象所指向的地址就会发生改变。下面我们先来看几个例子:

list1 = [1, 2, 3, [4, 5, 6]]
print(f"id_list1[0]:{id(list1[0])},id_list1[3]:{id(list1[3])}")
list1[0] = 9
list1[3].append(7)
print(list1)
print(f"id_list1[0]{id(list1[0])},id_list1[3]{id(list1[3])}")
id_list1[0]:140714489245952,id_list1[3]:2631977918984
[9, 2, 3, [4, 5, 6, 7]]
id_list1[0]140714489246208,id_list1[3]2631977918984

我们把注意力放到list1列表里的对象上,我们可以看出list1[0] (内存地址变化)是不可变对象,list1[3] (内存地址不变)作为一个列表是可变对象。
我们在遇到深拷贝和浅拷贝的时候,需要注意的也是这些问题,下面以实例讲解:

list1 = [1, 2, 3, [4, 5, 6]]
list2=list1 #赋值引用
list3=list1.copy()          #浅拷贝
list4=copy.deepcopy(list1)  #深拷贝

print(f"list1:{list1},id_list1:{id(list1)},id_list1[3]:{id(list1[3])}")
print(f"list2:{list2},id_list2:{id(list2)},id_list2[3]:{id(list2[3])}")
print(f"list3:{list3},id_list3:{id(list3)},id_list3[3]:{id(list3[3])}")
print(f"list4:{list4},id_list4:{id(list4)},id_list4[3]:{id(list4[3])}")

list1.append(7) #对列表list1进行添加
list1[3].append(8)  #对列表list1里的[4,5,6]进行添加

print(f"list1:{list1},id_list1:{id(list1)},id_list1[3]:{id(list1[3])}")
print(f"list2:{list2},id_list2:{id(list2)},id_list2[3]:{id(list2[3])}")
print(f"list3:{list3},id_list3:{id(list3)},id_list3[3]:{id(list3[3])}")
print(f"list4:{list4},id_list4:{id(list4)},id_list4[3]:{id(list4[3])}")

结果如下:

list1:[1, 2, 3, [4, 5, 6]],id_list1:1749900126344,id_list1[3]:1749900127368
list2:[1, 2, 3, [4, 5, 6]],id_list2:1749900126344,id_list2[3]:1749900127368
list3:[1, 2, 3, [4, 5, 6]],id_list3:1749900124936,id_list3[3]:1749900127368
list4:[1, 2, 3, [4, 5, 6]],id_list4:1749901280456,id_list4[3]:1749900126600

list1:[1, 2, 3, [4, 5, 6, 8], 7],id_list1:1749900126344,id_list1[3]:1749900127368
list2:[1, 2, 3, [4, 5, 6, 8], 7],id_list2:1749900126344,id_list2[3]:1749900127368
list3:[1, 2, 3, [4, 5, 6, 8]],id_list3:1749900124936,id_list3[3]:1749900127368
list4:[1, 2, 3, [4, 5, 6]],id_list4:1749901280456,id_list4[3]:1749900126600

由于python是动态语言,我们在list2=list1的时候并list2没有新开辟一个地址空间来进行存储,而是引用了list1的地址空间,也正因为这样我们在对list1进行修改的时候,list2也会相应的改变。
接下来就是浅拷贝了,既然是浅拷贝,顾名思义,拷贝的应该不是特别干脆,我们将list1list3前后对比可以发现,list1list3的内存地址相同,list1[3]list3[3] 内存地址相同,浅拷贝在拷贝的时候除了拷贝了不可变对象的内存地址,在拷贝 list1[3] 的时候把[4,5,6]作为一个可变对象并将它的内存地址拷贝下来,也因此在后来 list1[3] 添加元素后,对应的我们在输出 list3[3] 的时候计算机去访问的是之前[4,5,6]这个对象所在的地址,结果现在这个地址又增加了一个8 所以输出了[4,5,6,8],而7只是添加给了list1,所以list3 没有7。
深拷贝就比较简单了,就是拷贝的很彻底,就是相当于另外一个空间里就存了一份,跟之前的一点关系也没有,所以之前的无论如何变化,深拷贝的都不会发生变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值