Python 浅拷贝 深拷贝

Python 浅拷贝  深拷贝
浅拷贝与深拷贝直接赋值对象的引用别名不产生拷贝浅拷贝拷贝父对象不会拷贝对象的内部的子对象。拷贝后只有第一层是独立的深拷贝完全拷贝了父对象及其子对象。拷贝后所有层都是独立的。方式是否生成新父对象是否拷贝嵌套子对象数据独立性适用场景直接赋值否否完全不独立仅需引用对象无需修改数据浅拷贝是否第一层独立深层不独立对象无嵌套可变元素追求高效深拷贝是是递归所有层级完全独立对象存在嵌套可变元素需要数据隔离如何浅拷贝列表切片list[:]最简洁仅适用于列表工厂函数list()、set()、dict()通用序列/字典浅拷贝copy模块copy.copy()通用所有可拷贝对象案例1创建一个列表其中包含整型和列表元素使用copy()函数对其浅拷贝。使用id()查看列表地址和列表中每个元素的地址。import copy # 导入copy模块 # 定义原列表第一层不可变元素第三层嵌套可变列表 list1 [1, 2, 3, [100, 200, 300]] print( 原列表初始状态 ) print(原列表list1:, list1) print(list1外层内存地址:, id(list1)) print(list1[0]int元素地址:, id(list1[0])) print(list1[1]int元素地址:, id(list1[1])) print(list1[2]int元素地址:, id(list1[2])) print(list1[3]嵌套列表地址:, id(list1[3])) # 浅拷贝生成新列表list2 list2 copy.copy(list1) print(\n 浅拷贝后新列表初始状态 ) print(拷贝后列表list2:, list2) print(list2外层内存地址:, id(list2)) print(list2[0]int元素地址:, id(list2[0])) print(list2[1]int元素地址:, id(list2[1])) print(list2[2]int元素地址:, id(list2[2])) print(list2[3]嵌套列表地址:, id(list2[3]))可以看到拷贝后的新列表地址改变了但列表各个元素还是同一地址此时修改list1[0]类型元素# 修改原列表第一层int元素不可变类型 list1[0] 100 print(\n 修改第一层不可变元素后 ) print(原列表list1:, list1, 地址:, id(list1), 索引0地址:, id(list1[0])) print(拷贝列表list2:, list2, 地址:, id(list2), 索引0地址:, id(list2[0]))因为int是不可变类型修改时会直接开辟新内存空间、生成新对象不会影响原引用因此浅拷贝后的第一层数据相互独立。修改list[3]列表元素# 修改原列表深层嵌套列表可变类型 list1[3].append(400) print(\n 修改深层可变元素后 ) print(原列表list1:, list1, 索引3地址:, id(list1[3])) print(拷贝列表list2:, list2, 索引3地址:, id(list2[3]))原列表和拷贝列表的嵌套列表同时新增400数据同步变化。因为嵌套list是可变类型浅拷贝未复制深层子对象二者共用同一个内存地址原地修改数据会影响所有引用该对象的变量。如何深拷贝通过copy.deepcopy()实现递归全层级拷贝适配所有嵌套数据结构列表、字典、自定义对象等。案例1创建一个列表其中包含整型和列表元素使用deepcopy()对其深拷贝。使用id()查看列表地址和列表中各个元素的地址。import copy # 定义嵌套测试列表 list1 [1, 2, 3, [100, 200, 300]] print( 深拷贝前原列表状态 ) print(list1数据:, list1) print(list1地址:, id(list1), 嵌套列表地址:, id(list1[3])) # 深拷贝生成全新列表list3 list3 copy.deepcopy(list1) print(\n 深拷贝后新列表状态 ) print(list3数据:, list3) print(list3地址:, id(list3), 嵌套列表地址:, id(list3[3]))初始结果分析外层列表地址完全不同深层嵌套可变列表地址完全不同完成递归拷贝不可变元素int地址不变Python缓存机制节省内存不影响数据独立性。修改list[0]整型元素和list[3]列表元素# 1. 修改第一层不可变元素 list1[0] 100 # 2. 修改深层嵌套可变元素 list1[3].append(400) print(\n 修改原列表后对比 ) print(原列表list1:, list1) print(深拷贝列表list3:, list3)最终现象原列表数据完全修改深拷贝后的list3无任何变化真正实现数据完全隔离、互不干扰。补充元组的特殊拷贝特性元组是不可变类型但如果元组包含嵌套可变对象浅拷贝依然会共享子对象引用深拷贝一人会递归复制和列表逻辑一致import copy t1 (1, [2, 3]) t2 copy.copy(t1) t3 copy.deepcopy(t1) print(id(t1[1]) id(t2[1])) # True 浅拷贝共享子对象 print(id(t1[1]) id(t3[1])) # False 深拷贝完全独立