Python-引用&浅拷贝&深拷贝
浅拷贝: 指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用
深拷贝: 指的是重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中
对于可变对象深浅拷贝:
=浅拷贝:值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等
对于不可变对象的深浅拷贝:
不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
#codding: utf-8
"""
常量值: 在整个程序的完整生命周期中只会创建一次的变量被称为常量
1、str、int、 float、bool 这四个类型的值都是常量值,下面的例子中不论怎么操作都不会创建一个新的值
"""
import copy
a = "cpython" #创建常量
b = a #引用
c = copy.copy(a) #浅拷贝
d = copy.deepcopy(a) #深拷贝
"""
执行结果:
id(a)
Out[12]: 140347862604464
id(b)
Out[13]: 140347862604464
id(c)
Out[14]: 140347862604464
id(d)
Out[15]: 140347862604464
"""
a = 10 #创建常量
b = a #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[20]: 140348122786384
id(b)
Out[21]: 140348122786384
id(c)
Out[22]: 140348122786384
id(d)
Out[23]: 140348122786384
a = 2.4 #创建常量
b = a #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[28]: 140347862758640
id(b)
Out[29]: 140347862758640
id(c)
Out[30]: 140347862758640
id(d)
Out[31]: 140347862758640
a = True #创建常量
b = a #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[36]: 4502985424
id(b)
Out[37]: 4502985424
id(c)
Out[38]: 4502985424
id(d)
Out[39]: 4502985424
'''
#对象值:除了常量值以外,其他一切都是对象(类),例如:class, list, dict, tuple, set, queue, deque....
#对象的特征是,每次实例化一个对象都会创建new一个新内存,因此每次实例化一个对象,它们的id都是独立的
'''
a = []
b = []
id(a)
Out[42]: 140348133547520
id(b)
Out[43]: 140347588520896
class TEST:
def __init__(self):
self.world = "world"
a = TEST()
b = TEST()
id(a)
Out[51]: 140348133753232
id(b)
Out[52]: 140347862738592
#引用: python采取完全引用策略,所以像做下面这种操作,并不是复制/拷贝,而是引用
a = [] #实例化一个列表对象,变量a的指针指向该列表对象
b = a #变量b的指针指向a所指向的列表对象
id(a)
Out[55]: 140348133760384
id(b)
Out[56]: 140348133760384
### 拷贝
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[61]: 140348135105280
id(b)
Out[62]: 140348135105280
id(c)
Out[63]: 140348135105664 #c分配了一块新的内存
id(d)
Out[64]: 140348133627136 #d分配了一块新的内存
id(a[0])
Out[65]: 140348122786096
id(b[0])
Out[66]: 140348122786096 #成员值是常量,拷贝的是引用
id(c[0])
Out[67]: 140348122786096 #成员值是常量,拷贝的是引用
id(d[0])
Out[68]: 140348122786096 #成员值是常量,拷贝的是引用
##浅拷贝
a = [1,2,3,[4,5,6]]
b = a
c = copy.copy(a)
id(a[3])
Out[75]: 140348133697664
id(b[3])
Out[76]: 140348133697664
id(c[3])
Out[77]: 140348133697664
Out[77]: 140348133697664
a[3][0]= 10 #a[3]发生变化
Out[77]: 140348133697664
b #b[3]引用a[3],所以b[3]也发生变化
Out[79]: [1, 2, 3, [10, 5, 6]]
c
Out[80]: [1, 2, 3, [10, 5, 6]]
b[3][1] = 20 #b[3]的子对象发生变化
b
Out[82]: [1, 2, 3, [10, 20, 6]]
a #a[3]的子对象也会发生变化
Out[83]: [1, 2, 3, [10, 20, 6]]
c
Out[84]: [1, 2, 3, [10, 20, 6]]
#深拷贝
a = [1,2,3,[4,5,6]]
b = copy.deepcopy(a)
id(a)
Out[87]: 140348133734144 #分配一块新的内存
id(b)
Out[88]: 140348133698496 #分配一块新的内存
a[3][0]=10
a
Out[90]: [1, 2, 3, [10, 5, 6]] #a对象中的子对象发生变化
b
Out[91]: [1, 2, 3, [4, 5, 6]] #b对象中的子对象仍不变
'''
###结论:
1、不论是浅拷贝还是深拷贝,都不拷贝最终的常量值,而是引用
2、浅拷贝引用的是一维的成员
3、深拷贝递归的是创建对象,只有遇到常量值是会引用
'''
三十六般武艺,七十二般变化,修练出个人品牌并发出光芒
分类:
Python3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律