前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python基础之深浅copy

python基础之深浅copy

作者头像
天钧
发布2019-07-26 17:33:02
3580
发布2019-07-26 17:33:02
举报
文章被收录于专栏:渗透云笔记渗透云笔记

引子

首先在了解python中的深浅拷贝之前,我们先花一点时间来了解一下python内存中变量的存储情况。对于python而言,变量的存储采用了引用语义的方式,存储的只是一个变量值所在的内存地址,而不是这个变量的本身。

首先大家先思考一个问题:b = ?

代码语言:javascript
复制
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 3
>>> b = a
>>> a = 5

正确答案是3。为什么呢?根据上面的解释可以的知变量在引用的过程中调用的并非变量的值,而是该变量所存储的内存地址。

代码语言:javascript
复制
>>> a = 3
>>> b = a
>>> id(a)
1460043952
>>> id(b)
1460043952
>>> a = 5
>>> id(a)
1460044016

由于变量b指向的变量a的内存地址也就是‘1460043952‘,而在给a重新赋值的情况下a的内存地址发生了变化而b原本指向的就是a重新赋值前的内存地址。因此即使在给a重新赋值的情况下b也不会发生变化。

赋值

作用:数据间的引用

代码语言:javascript
复制
>>> l1 = [1,2,3]
>>> l2 = l1
>>> l1[0] = 4
>>> l1,l2
([4, 2, 3], [4, 2, 3])

由于上面写的比较详细了这里就不进行验证操作了通过id()函数自行查看内存地址进行验证

浅拷贝

作用:拷贝一份独立的数据,不包括子元素

浅拷贝的使用

代码语言:javascript
复制
# 方式一
>>> import copy
>>> a = 1
>>> b = copy.copy(a)

# 方式二
>>> l1  = [1,2,3,4]
>>> l2 = l1.copy()
>>> l2

浅拷贝的重新赋值操作

代码语言:javascript
复制
>>> l1  = [1,2,[3,4]]
>>> l2 = l1.copy()
>>> l2
[1, 2, [3, 4]]
>>> l1[1]=5
>>> l1,l2
([1, 5, [3, 4]], [1, 2, [3, 4]])
>>> l1[2].append(6)
>>> l1,l2
([1, 5, [3, 4, 6]], [1, 2, [3, 4, 6]])

通过上面的例子可以看出浅拷贝拷贝的是一份独立的列表,如果列表中嵌套了列表的话,子列表是不独立的(引用)。

验证:

代码语言:javascript
复制
>>> id(l1)
1655770326088
>>> id(l2)
1655768753672
# 通过内存地址查看两个列表的内存地址是不同的
>>> id(l1[0])
1460043888
>>> id(l2[0])
1460043888
# 通过内存地址查看两个列表中的元素内存地址相同
>>> id(l1[2])
1655770326024
>>> id(l2[2])
1655770326024
>>> id(l1[2][0])
1460043952
>>> id(l2[2][0])
1460043952
# 通过内存地址查看两个列表中的子列表内存地址完全相同(子列表共享)

普通列表:由于列表与列表中的元素的内存地址都是独立的,而浅拷贝则是给新的列表重新开辟一块内存地址,而列表总的元素则使用原列表的内存地址。如果对某个列表中的元素重新赋值,则会开辟新的内存地址,因此两个列表之间互相影响。

嵌套列表:,由于子列表是两个列表共享的,因此子列表并不是有单独的内存地址,,所以修改子列表中的值,两个列表都会受影响。

深拷贝

作用拷贝一份完全独立的数据

深拷贝的使用:

代码语言:javascript
复制
>>> import copy
>>> l1 = [1,2,3,[4,5]]
>>> l2 = copy.deepcopy(l1)
>>> l1,l2
([1, 2, 3, [4, 5]], [1, 2, 3, [4, 5]])

深拷贝的重新赋值操作

代码语言:javascript
复制
>>> l1[0] = 0
>>> l1,l2
([0, 2, 3, [4, 5]], [1, 2, 3, [4, 5]])
>>> l1[3][0] = 6
>>> l1,l2
([0, 2, 3, [6, 5]], [1, 2, 3, [4, 5]])

验证:

代码语言:javascript
复制
>>> id(l1[0])
1460043856
>>> id(l2[0])
1460043888
>>> id(l1[3])
1655770201544
>>> id(l2[3])
1655770325832
>>> id(l2[3][0])
1460043984
>>> id(l1[3][0])
1460044048

通过查看内存地址发现无论是列表中的元素还是子元素的内存地址都是完全独立的。由此可得通过深拷贝拷贝出来的数据是完全独立的

补充:

以上说明仅限与可变类型。

不可变类型的深浅copy都不会开辟新的内存空间

代码语言:javascript
复制
>>> a = 'hello world'
>>> b = copy.copy(a)
>>> a,b
('hello world', 'hello world')
>>> id(a),id(b)
(1655768754224, 1655768754224)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 渗透云笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引子
  • 赋值
  • 浅拷贝
  • 深拷贝
  • 补充:
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档