深入理解Python中赋值、深拷贝(deepcopy)、浅拷贝(copy)
赋值
python跟java中的变量本质是不一样的,Python的变量实质上是一个指针(int型或str型),而java的变量是一个可操作的存储空间。
- a = 123
b = a- print(id(a))
print(id(b))- print(a is b)
- result:
26848576
26848576
True
这里可以看到a和b的地址是一样的,a=123,实质上是将a这个对象"贴到"123上;同样,b=a,也是将b这个对象“贴到”123上,这里变量实际上是个“便利贴“。
下面用一个可变的对象list来做说明:
- a = [1, 2, 3]
- b = a
- a.append(4)
- a[0] = 6
- print(a)
- print(b)
- result:
- [6, 2, 3, 4]
- [6, 2, 3, 4]
首先把a和b贴在 [1,2,3]这个对象上,然后通过append,[1,2,3]这个对象变成了[1,2,3,4],再通过a[0]=6,将对象[1,2,3,4]的第0个元素地址对应值改为6,
则最终这个对象是[6,2,3,4],然而a和b仍然是贴在这个对象上的,即a和b都是[6,2,3,4]
浅拷贝(copy)
对于浅拷贝有两种情况:
1. 浅拷贝值是不可变对象(数值,字符串,元组)时,等同于赋值,对象的id值与浅拷贝原来的值相同。
- import copy
- a = 1
- b = a
- c = copy.copy(a)
- print(id(a))
- print(id(b))
- print(id(c))
- result:
- 35258712
- 35258712
- 35258712
2. 浅拷贝值是可变对象(list,dict)时:
2.1 不包含子对象
- # coding:utf-8
- import copy
- a = [1, 2, 3]
- b = a
- c = copy.copy(a)
- print("append前c={}".format(id(c)))
- a.append(4)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("append后c={}".format(id(c)))
- print("a值={}".format(a))
- print("b值={}".format(b))
- print("c值={}".format(c))
- result:
- append前c=139982846485352
- a=139982846912272
- b=139982846912272
- append后c=139982846485352
- a值=[1, 2, 3, 4]
- b值=[1, 2, 3, 4]
- c值=[1, 2, 3]
对于不包含子对象的情况下,原值的改变并不会影响浅拷贝的值,同时浅复制的值改变也并不会影响原值,并且浅拷贝是新开辟的一块内存,与原对象内存地址不同。
2.2 包含子对象
- # coding:utf-8
- import copy
- a = [1, [4], 2, 3]
- b = a
- c = copy.copy(a)
- print("append前c={}".format(id(c)))
- a.append(5)
- a[1].append(9)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("append后c={}".format(id(c)))
- print("a值={}".format(a))
- print("b值={}".format(b))
- print("c值={}".format(c))
- result:
- append前c=140519703466856
- a=140519703889752
- b=140519703889752
- append后c=140519703466856
- a值=[1, [4, 9], 2, 3, 5]
- b值=[1, [4, 9], 2, 3, 5]
- c值=[1, [4, 9], 2, 3]
可以看出,浅拷贝只拷贝父对象([1,2,3]),不会拷贝对象内部的子对象([4]),改变原对象中复杂子对象的值时会改变浅拷贝的值。
深拷贝(deepcopy)
- # coding:utf-8
- import copy
- a = [1, [4], 2, 3]
- print("a原始值={}".format(a))
- b = a
- d = copy.deepcopy(a)
- a.append(5)
- a[1].append(9)
- print("a={}".format(id(a)))
- print("b={}".format(id(b)))
- print("d={}".format(id(d)))
- print("a值={}".format(a))
- print("b值={}".format(b))
- print("d值={}".format(d))
- result:
- a原始值=[1, [4], 2, 3]
- a=139675956164440
- b=139675956164440
- d=139675955741904
- a值=[1, [4, 9], 2, 3, 5]
- b值=[1, [4, 9], 2, 3, 5]
- d值=[1, [4], 2, 3]
深拷贝则会拷贝对象及其子对象,深拷贝的时候会将复杂对象的每一层复制一个单独的个体出来,原对象的值改变时并不会影响deepcopy的值,
但是,由于深拷贝需要维护一个 内存 用于记录已经拷贝的对象,所以深拷贝的速度会比较慢。
深入理解Python中赋值、深拷贝(deepcopy)、浅拷贝(copy)的更多相关文章
- **Python中的深拷贝和浅拷贝详解
Python中的深拷贝和浅拷贝详解 这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容. 要说清楚Python中的深浅拷贝,需要 ...
- 001 说说Python中的深拷贝和浅拷贝
在Python编程中忽略深拷贝和浅拷贝可能会造成未知的风险. 比如我们打算保存一份原始对象的副本作为上一状态的记录,此后修改原始对象数据时,若是副本对象的数据也发生改变,那么这就是一个严重的错误. 注 ...
- python中的深拷贝和浅拷贝理解
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用.以下分两个思路来分别理解浅拷贝和深拷贝: 利用切 ...
- python中的深拷贝与浅拷贝
深拷贝和浅拷贝 浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变. 1.对象的赋值 对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷 ...
- python中的深拷贝和浅拷贝
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一 ...
- 低门槛彻底理解JavaScript中的深拷贝和浅拷贝
作者 | 吴胜斌 来源 | https://www.simbawu.com/article/search/9 在说深拷贝与浅拷贝前,我们先看两个简单的案例: //案例1var num1 = 1, nu ...
- 理解JavaScript中的深拷贝和浅拷贝
, num2 = num1;console.log(num1) //1console.log(num2) //1num2 = 2; //修改num2console.log(num1) //1conso ...
- Python 中的深拷贝和浅拷贝
一.浅拷贝python中 对象赋值时 默认是浅拷贝,满足如下规律:1. 对于 不可变对象(字符串,元组 等),赋值 实际上是创建一个新的对象:例如: >>> person=['nam ...
- python中的深拷贝和浅拷贝(面试题二)
一.浅拷贝 定义:浅拷贝只是对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值. 浅拷贝的特点: 公用一个值: 这两个变量的内存地址一样: 对其中一个变量的值改变,另外一个变量的值也 ...
随机推荐
- 图解elasticsearch的_source、_all、store和index
Elasticsearch中有几个关键属性容易混淆,很多人搞不清楚_source字段里存储的是什么?store属性的true或false和_source字段有什么关系?store属性设置为true和_ ...
- 洛谷P5219 无聊的水题 I [prufer序列,生成函数,NTT]
传送门 思路 有标号无根树的计数,还和度数有关,显然可以想到prufer序列. 问题就等价于求长度为\(n-2\),值域为\([1,n]\),出现次数最多的恰好出现\(m-1\)次,这样的序列有哪些. ...
- jenkins 安装网址
https://wiki.jenkins.io/display/JENKINS/Installing+Jenkins
- Struts2中类数据封装的方式
第一种方式:属性驱动提供对应属性的set方法进行数据的封装.表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可.表单中的数据提交,最终找到Action类中的setXxx ...
- yum -y 与yum有何区别(转载)
在linux中,经常使用yum来进行软件的安装,更新与卸载,那我们会发现,在使用yum的时候,通常有下面两种指令模式: ①yum install xxx ②yum -y install ...
- 各数据库连接maven配置
Derbydb driver maven dependency<dependency> <groupId>org.apache.derby</groupId> &l ...
- 1,环境的搭建,angular
也是学习一些皮毛,只是把这些经验记录下来而已. 至于angular有什么好处,或者有什么是什么,我就不多做介绍,自己可以去百度,肯定能找到更为详细的. 我使用的是google提供的angualr-cl ...
- selenium 操作键盘
send_keys(Keys.ENTER) 按下回车键send_keys(Keys.TAB) 按下Tab制表键send_keys(Keys.SPACE) 按下空格键spacesend_keys(Kye ...
- jenkins 回滚发布
#jenkins拉取文件路径 workspace=/data/wos/testtemp #备份路径 backspace=/data/wos/back #不能提Git的文件 config=/data/w ...
- C++ Primer 笔记——类成员指针
1.当我们初始化一个成员指针或为成员指针赋值时,该指针并没有指向任何数据.成员指针指定了成员而非成员所属的对象,只有当解引用成员指针时,我们才提供对象信息. 2.和普通的函数指针类似,如果成员存在重载 ...