Python基础知识点之深浅copy
一、数字和字符串的拷贝
赋值
>>> a=1
>>> b=1
>>> id(a)
140736094983200
>>> id(b)
140736094983200
python中有一个重用机制,对于同一个数字,python并不会开辟一块新的内存空间,而是维护同一块内存地址,只是将该数字对应的内存地址的引用赋值给变量a和a。所以根据输出结果,a和b其实对应的是同一块内存地址,只是两个不同的引用罢了。同样的,对于a = b,其实效果等同于“a = 1; b = 1”,它也就是将a指向1的引用赋值给b。字符串跟数字的原理雷同,如果把1改成“abc”也是一样的。
结论:对于通过用 = 号赋值,数字和字符串在内存当中用的都是同一块地址。
浅copy
>>> import copy
>>> a1=123
>>> id(a1)
140736094987104
>>> a2=copy.copy(a1)
>>> id(a2)
140736094987104
通过copy中的copy()进行浅copy,把a1拷贝一份给a2,发现a1和a2的内存地址还是一样。
结论:对于浅copy来说,数字和字符串在内存中用的也是同一块地址。
深copy
>>> import copy
>>> b1=123
>>> b2=copy.deepcopy(b1)
>>>> id(b1)
140736094987104
>>> id(b2)
140736094987104
查看结果发现,对于深拷贝,数字和字符串在内存当中用的也是同一块地址。
结论:所以综上所述,对于数字和字符串的赋值、浅拷贝、深拷贝在内存当中用的都是同一块地址。
原理如下图:
二、字典、列表、元组等其他类型的拷贝
赋值
>>> n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
>>> n2 = n1
>>> id(n1)
1643345359208
>>> id(n2)
1643345359208
原理如下图:
结论 : 对于赋值,字典、列表、元组等其他类型用的内存地址不会变化。
浅copy
>>> n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
>>> n3 = copy.copy(n1)
>>> id(n1)
1643345359280
>>> id(n3)
1643345359712
>>> id(n1["k1"])
1643345119024
>>> id(n3["k1"])
1643345119024
以上结果可以看出,进行浅拷贝时,我们的字典第一层n1和n3指向的内存地址已经改变了,但是对于第二层里的列表并没有拷贝,它的内存地址还是一样的。
原理如下图:
结论: 所以对于浅拷贝,字典、列表、元组等类型,它们只拷贝第一层地址。
深copy
>>> b1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
>>> b2 = copy.deepcopy(b1)
>>> id(b1)
1643345086864
>>> id(b2)
1643345359928
>>> id(b1["k3"])
1643345364552
>>> id(b2["k3"])
1643345037704
>>> id(b1["k1"])
1643345119024
>>> id(b2["k1"])
1643345119024
通过以上结果发现,进行深拷贝时,字典里面的第一层和里面嵌套的地址都已经变了。对于深拷贝,它会拷贝多层,将第二层的列表也拷贝一份,如果还有第三层嵌套,那么第三层的也会拷贝,但是对于里面的最小元素,比如数字和字符串,这里就是“wu”,123,“alex”,678之类的,按照python的机制,它们会共同指向同一个位置,它的内存地址是不会变的。
原理如下图:
结论:对于深拷贝,字典、列表、元组等类型,它里面嵌套多少层,就会拷贝多少层出来,但是最底层的数字和字符串地址不变。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步