Python 之 = [:] copy deepcopy
写在前面
已经见多很多这样的Blog,为什么还想自己写呢?原因很简单,每当学到一个知识时候,尝试着对自己或者别人讲解这个知识点,当别人能听懂的时候,就算是真的理解了。
重要部分
首先,要分清楚id()函数、is和= =运算符 的使用以及区别。id()是返回一个对象的地址;is 比较两个变量的引用是否指向同一个对象;= = 比较两个变量的值是否相等
其次,Python中一切皆对象,所有的对象拥有三个属性:id、type、value,Python对象分两种类型,一是不可变对象,二是可变对象。
不可变对象:该对象所指向的内存中的值不能被改变。一个变量指向的是不可变对象的引用,当对这个变量的值做修改时,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,这时变量的指向已经发生改变,由原来的指向新开辟的地址。
可变对象:该对象所指向的内存中的值可以被改变。变量改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,变量指向的地址并没有发生改变。
a = 100 #id(a) ->140736904075200
a += 10 #id(a) ->140736904078400
L = ['C#', 'C++', 'Java'] #id(L) ->1627814636224
L.append('Python') #id(L) ->1627814636224
常见的不可变对象:数字、字符串、元组
常见的可变对象:列表、字典、集合
接下来,看一下这个例子
import copy
is_same_addr = lambda v1,v2:(id(v1)==id(v2))e = 10 #e指向不可变对象
v_1 = e #直接赋值
v_2 = copy.copy(e) #浅拷贝
print is_same_addr(v_1, e) #>> True
print is_same_addr(v_2, e) #>> True
显然,当变量e指向的是不可变对象,采用直接赋值或者拷贝的方式让另一个变量v等于e,实际上两个变量指向的是同一个变量的引用,并没有复制出新的副本
接着,再往下看
e = ['e','jianl', ['Python', 'C++']]
v_1 = e #1 赋值
v_2 = e[:] #2 切片
v_3 = copy.copy(e) #3 浅拷贝
v_4 = copy.deepcopy(e) #4 深拷贝print is_same_addr(v_1, e) #>> True
print is_same_addr(v_2, e) #>> False
print is_same_addr(v_3, e) #>> False
print is_same_addr(v_4, e) #>> False
可以看出,除了赋值的方式是复制变量e的引用外, 其余方式都是有开辟新的内存,不算是 ‘假复制’,
因此,我想如果v_2 、v_3、 v_4 不小心发生改变,应该不会影响原变量e的值,依据是他们所指向并不是同一个对象, 真的是这样吗?敲代码看一下
v_2[0] = 'v_2'
v_3[0] = 'v_3'
v_4[0] = 'v_4'
# 输出各个变量的值
>> e : ['e', 'jianl', ['Python', 'C++']]
>> v_1: ['e', 'jianl', ['Python', 'C++']]
>
>> v_2: ['v_2', 'jianl', ['Python', 'C++']]
>> v_3: ['v_3', 'jianl', ['Python', 'C++']]
>> v_4: ['v_4', 'jianl', ['Python', 'C++']]
似乎是这样,不过到这里还没完,接着试一下对列表里的可变对象修改操作,看下结果又会怎样呢?
v_2[2][0] = 'C#'
v_3[2][0] = 'C#'
分别对v_2[2] 、v_3[2]所指向的列表作同样的修改,两种情况输出的结果一致,而且变量e的值被修改了
e : ['e', 'jianl', ['C#', 'C++']]
v_1: ['e', 'jianl', ['C#', 'C++']]
v_2: ['e', 'jianl', ['C#', 'C++']]
v_3: ['e', 'jianl', ['C#', 'C++']]
v_4: ['e', 'jianl', ['Python', 'C++']]
同样,再对v_4[2]所指向的列表作同样的修改
v_4[2][0] = 'C#'
结果,只有v_4的值被修改了
e : ['e', 'jianl', ['Python', 'C++']]
v_1: ['e', 'jianl', ['Python', 'C++']]
v_2: ['e', 'jianl', ['Python', 'C++']]
v_3: ['e', 'jianl', ['Python', 'C++']]
v_4: ['e', 'jianl', ['C#', 'C++']]
为什么会这样呢?来做一个验证, 对比变量指向的对象成员中为可变变量的地址
print is_same_addr(v_1, e),is_same_addr(v_1[2], e[2]) #True True
print is_same_addr(v_2, e),is_same_addr(v_2[2], e[2]) #False True
print is_same_addr(v_3, e),is_same_addr(v_3[2], e[2]) #False True
print is_same_addr(v_3, e),is_same_addr(v_4[2], e[2]) #False False
水落石出,利用切片[:]属性或者copy()函数实现对一个变量赋值,属于浅拷贝,只是拷贝对象的一部分不可变类型的数据,对于对象里的可变类型对象属性,仅仅是拷贝一个引用;而使用deepcopy()函数实现的是深拷贝,将变量所指向的对象整个复制,开辟新的空间,再由另一个变量指向这块新的空间。
最后
几句话总结:
1 对象有类型,变量无类型,变量是对象的标签;
2 对指向不可变对象变量的值作修改,实际上是改变变量的指向,对象本身是不可能被修改的;指向可变对象变量的值发生改变,实际上是对象本身被修改了;
3 v = e,实际上是将e的引用赋值给v, v e指向同一个变量;
4 v= e[:] 及 v=copy(e),浅拷贝,只复制部分数据,而e所指向的对象中可变类型属性,只是拷贝引用;
5 v = deepcopy(e), 深拷贝,e指向的整个对象被复制,再由v指向;
参考文章:
https://www.jianshu.com/p/9ed9b5ce7bb0
Python 之 = [:] copy deepcopy相关推荐
- Python中copy,deepcopy,浅拷贝(“=”)和深拷贝(“copy.deepcopy()”)
python中对于对象的拷贝分为浅拷贝(copy)和深拷贝(deepcopy)两种方式.其中浅拷贝由"="完成.而深拷贝由copy模块中deepcopy()函数担任. 浅拷贝和深拷 ...
- 浅拷贝copy(“=”)和深拷贝(“copy.deepcopy()”)
python中对于对象的拷贝分为浅拷贝(copy)和深拷贝(deepcopy)两种方式. 其中浅拷贝由"="完成.而深拷贝由copy模块中deepcopy()函数担任. 浅拷贝和深 ...
- Python 传值和传址 copy/deepcopy
传值:被调函数局部变量改变不会影响主调函数局部变量 传址:被调函数局部变量改变会影响主调函数局部变量 Python参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值:如 ...
- [PYTHON] 深度解析copy.copy() 与 copy.deepcopy()
在列表中,想要复制一个列表,可以使用copy()函数,在列表中,copy()函数与切片 [:] 功能相同 a=[0,1,[0,1]] b=a.copy() c=a[:] -----print b,c- ...
- 2020-09-18 python中copy()和deepcopy()详解
首先直接上结论: -–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在.所以改变原有被复制对象不会对已经复制出来的新对象产生影响. -–而浅复制并不会产生一个独立的对 ...
- python中copy()和deepcopy()详解
参考文章 http://iaman.actor/blog/2016/04/17/copy-in-python **首先直接上结论: -–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独 ...
- Python中copy和deepcopy中的区别
最近在学习 Python编程,遇到copy和deepcopy感到很困惑,现在针对这两个方法进行区分,一种是浅复制(copy),一种是深度复制(deepcopy). 首先说一下deepcopy,所谓的深 ...
- python中copy和deepcopy详细区别
python中copy和deepcopy 在 python 中,标识一个对象唯一身份的是:对象的id(内存地址),对象类型,对象值. deepcopy是真正意义上的复制,深拷贝,被复制对象完全复制一遍 ...
- Python中copy()和deepcopy()的区别
同样是copy,二者有什么不同呢今天我们就一探究竟!!! 关于copy()和deepcopy()的第一篇博客 初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从 ...
最新文章
- codeblocks使用指南
- 李德毅院士:通用人工智能十问
- Java NIO(十五) Path 的用法
- C++设计模式实现--策略(Strategy)模式
- SqliteHelper整理(转载)
- hibernate 表关系映射详解之多对多
- 乐鑫esp8266的串口通讯驱动源文件,nonos和rtos版本
- 基于JAVA+SpringMVC+MYSQL的ktv预订管理系统
- js setInterval() 用法示例
- java中的银行界面开发_ATM机银行项目java图形界面
- html修改每页显示数量,JS实现动态设置每页显示固定行数
- 电子秤查看通道及更改通道方法
- 对策《四川省本科毕业论文(设计)抽检实施细则》(二)专业能力
- cv个人计算机SCI英文简历模板,个人英文简历模板
- 电脑发到,电脑电影怎么传到手机_把电脑上的电影传到手机上的详细教程
- 软件测试之测试用例设计(一)
- 为什么会出现锟斤拷?
- el-table展示枚举值
- 如何设计游戏中的道具功能(三)
- FPC软排线结构的奥秘
热门文章
- 个人计算机cache是什么意思,cache在计算机中的作用是什么?
- 深信服上网行为管理设备登录方法、恢复出厂、恢复控制台密码
- 无基础的人如何唱好歌、三分钟让你快速学会唱歌技巧
- [Qt] TCP客户端与服务器断开连接自动重联机制
- The authenticity of host ‘gree129 (192.168.**.129)‘ can‘t be established.
- Tita 持续绩效:一对一会议的好处
- 吉尔电子烟获1200万天使轮融资
- 古董电脑室:2019日记簿(二)
- 计算机硬件耗电,耗电大户不一定就“费电”_主板评测-中关村在线
- B端和C端产品的理解