当前位置: 首页 > article >正文

学习python的第十一天之数据类型——拷贝之浅拷贝和深拷贝

学习python的第十一天之数据类型——拷贝之浅拷贝和深拷贝

浅拷贝(Shallow Copy)

浅拷贝创建一个新的对象,但不复制嵌套的对象。原对象中的嵌套对象引用会被保持在新对象中,这意味着新对象和旧对象共享嵌套的对象。

特点:
  • 新对象和旧对象是独立的,但它们内部的引用指向相同的对象。
  • 修改新对象中的嵌套对象也会影响旧对象中的嵌套对象,因为它们是共享的。
实现方式:
  • 使用copy模块中的copy函数。
  • 使用某些内置方法,如列表的.copy()方法。
import copy

list1 = ['张三', 25, '男', [1, 3.14, '您好']]
list2 = list1.copy()
list3 = copy.copy(list1)

print(list1, id(list1))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1479882705920
print(list2, id(list2))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1479882706432
print(list3, id(list3))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1479882707392

for e1 in list1:
    print(e1, id(e1))
# 张三 1479913920624
# 25 1479877618736
# 男 1479914043552
# [1, 3.14, '您好'] 1479914011008

for e2 in list2:
    print(e2, id(e2))
# 张三 1479913920624
# 25 1479877618736
# 男 1479914043552
# [1, 3.14, '您好'] 1479914011008

for e3 in list3:
    print(e3, id(e3))
# 张三 1479913920624
# 25 1479877618736
# 男 1479914043552
# [1, 3.14, '您好'] 1479914011008

list1[0] = '李四'
print(list1, id(list1))  # 输出: ['李四', 25, '男', [1, 3.14, '您好']] 1479882705920
print(list2, id(list2))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1479882706432
print(list3, id(list3))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1479882707392

# 当只是修改浅层数据的时候,list2和list3的内容不会随着list1的内容变动而变动,
# 且list1、list2、list3的地址也不会变化
import copy

list1 = ['张三', 25, '男', [1, 3.14, '您好']]
list2 = list1.copy()
list3 = copy.copy(list1)

print(list1, id(list1))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1719205170176
print(list2, id(list2))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1719205170688
print(list3, id(list3))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 1719205171648
print(list2[3], id(list2[3]))  # 输出: [1, 3.14, '您好'] 1719236487872
print(list2[3][2], id(list2[3][2]))  # 输出: 您好 1719236450512

list2[3][2] = 'HELLO'
print(list1, id(list1))  # 输出: ['张三', 25, '男', [1, 3.14, 'HELLO']] 1719205170176
print(list2, id(list2))  # 输出: ['张三', 25, '男', [1, 3.14, 'HELLO']] 1719205170688
print(list3, id(list3))  # 输出: ['张三', 25, '男', [1, 3.14, 'HELLO']] 1719205171648
print(list2[3], id(list2[3]))  # 输出: [1, 3.14, 'HELLO'] 1719236487872
print(list2[3][2], id(list2[3][2]))  # 输出: HELLO 1719236513136

# 当修改深层次的数据时,因为列表的存储内容归根结底是每个元素的地址,
# 所以list1[3]存储的其实是[1, 3.14, '您好']的地址,
# 同理list2和list3也是一样,
# 前面说了,修改列表不会引起地址的改变,
# 所以将[1, 3.14, '您好']中的'您好'替换成'HELLO'后,[1, 3.14, 'HELLO']的地址不变,
# 所有list1[3]、list2[3]、list3[3]存储的地址所指引的内容就变成了[1, 3.14, 'HELLO'],
# 这也就是为什么只是修改了list2[3]中的一个元素,list1和list3都发生改变了;

# 另外为什么'您好'改为'HELLO'后,'您好'的地址和'HELLO'的地址发生了改变:
# 因为str字符串类型是不可变类型,内容发生改变后地址就会改变;
# 而list列表类型是可变类型,所以[1, 3.14, '您好']和[1, 3.14, 'HELLO']的地址没有发生改变;

在这里插入图片描述

深拷贝(Deep Copy)

深拷贝创建一个新的对象,并递归地复制所有嵌套的对象。这意味着新对象和旧对象在所有层级上都是独立的,修改新对象不会影响旧对象。

特点:
  • 新对象和旧对象是完全独立的,它们内部的引用指向不同的对象。
  • 修改新对象中的任何对象都不会影响旧对象。
实现方式:
  • 使用copy模块中的deepcopy函数。
import copy

list1 = ['张三', 25, '男', [1, 3.14, '您好']]
list2 = copy.deepcopy(list1)

print(list1, id(list1))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 2827084499840
print(list2, id(list2)) # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 2827084500352

for e1 in list1:
    print(e1, id(e1))
# 张三 2827115649136
# 25 2827075808304
# 男 2827115783472
# [1, 3.14, '您好'] 2827115751872

for e2 in list2:
    print(e2, id(e2))
# 张三 2827115649136
# 25 2827075808304
# 男 2827115783472
# [1, 3.14, '您好'] 2827084501312

# 从[1, 3.14, '您好']的地址可以看出,深拷贝的列表中可变类型元素,会有一个新地址,而不是像浅拷贝一样共用一个地址;

list2[0] = '李四'
print(list1, id(list1))  # 输出: ['张三', 25, '男', [1, 3.14, '您好']] 2827084499840
print(list2, id(list2)) # 输出: ['李四', 25, '男', [1, 3.14, '您好']] 2827084500352

list2[3][2] = 'HELLO'

for e1 in list1:
    print(e1, id(e1))
# 张三 2827115649136
# 25 2827075808304
# 男 2827115783472
# [1, 3.14, '您好'] 2827115751872

for e2 in list2:
    print(e2, id(e2))
# 李四 2827115710288
# 25 2827075808304
# 男 2827115783472
# [1, 3.14, 'HELLO'] 2827084501312

在这里插入图片描述

总结

  • 浅拷贝‌:复制了对象本身,但对象中的嵌套对象仍然是共享的。
  • 深拷贝‌:递归地复制了对象及其所有嵌套对象,使得新对象和旧对象完全独立。

选择浅拷贝还是深拷贝取决于你的具体需求。如果你只需要一个新的容器但里面的元素可以共享,浅拷贝是更高效的。如果你需要完全独立的对象副本,深拷贝是必须的。


http://www.kler.cn/a/402600.html

相关文章:

  • GPT系列文章
  • DataWhale—PumpkinBook(TASK05决策树)
  • ros2学习日记_241124_ros相关链接
  • 《第十部分》1.STM32之通信接口《精讲》之IIC通信---介绍
  • IEC61850读服务器目录命令——GetServerDirectory介绍
  • 基于STM32的火灾报警装置的Proteus仿真
  • 《macOS 开发环境配置与应用开发》
  • JSON 解析
  • 从JSON数据提取嵌套字段并转换为独立列的简洁方法
  • JMeter监听器与压测监控之Grafana
  • PostgreSQL外部表FDW【file_fdw】
  • 《现代制造技术与装备》是什么级别的期刊?是正规期刊吗?能评职称吗?
  • 等精度频率计的设计
  • 如何选择聚类算法、回归算法、分类算法?
  • 揭秘云计算 | 5、关于云计算效率的讨论
  • python学习笔记(3)运算符
  • Spring Boot 3.3高级日志配置详解:从 Logback 到 Log4j 2 的全面掌握
  • 优化移位寄存器
  • 【linux】线程概念与控制
  • HarmonyOS:UIAbility组件间交互(设备内)
  • SpringBoot(8)-任务
  • 阿里云IIS虚拟主机部署ssl证书
  • 汉诺塔(hanio)--C语言函数递归
  • 【提效工具开发】管理Python脚本执行系统实现页面展示
  • Android Studio启动模拟器显示超时
  • 基于BindingList的WinForm数据绑定机制与DataGridView动态刷新技术