【转】Python中的赋值、浅拷贝、深拷贝介绍
在学习过程中,一开始对浅拷贝理解很模糊。不过经过一系列的实验后,我发现对这三者的概念有了进一步的了解。
一、赋值
赋值算是这三种操作中最常见的了,我们通过一些例子来分析下赋值操作:
str例
>>> a = 'hello'
>>> b = 'hello'
>>> c = a
>>> [id(x) for x in a,b,c]
[4404120000, 4404120000, 4404120000]
由以上指令中,我们可以发现a, b, c三者的地址是一样的。所以以上赋值的操作就相当于c = a = b = 'hello'。
赋值是系统先给一个变量或者对象(这里是'hello')分配了内存,然后再将地址赋给a, b, c。所以它们的地址是相同的。
list例
>>> a = ['hello']
>>> b = ['hello']
>>> c = a
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
但是这种情况却不一样了,a和b的地址不同。为何?
因为str是不可变的,所以同样是'hello'只有一个地址,但是list是可变的,所以必须分配两个地址。
这时,我们希望探究以上两种情况如果 修改值 会如何?
str例
>>> a = 'world'
>>> [id(x) for x in a,b,c]
[4404120432, 4404120000, 4404120000]
>>> print a, b, c
world hello hello
这时a的地址和值变了,但是b, c地址和值都未变。因为str的不可变性,a要重新赋值则需重新开辟内存空间,所以a的值改变,a指向的地址改变。b, c由于'hello'的不变性,不会发生改变。
list例
>>> a[0] = 'world'
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
>>> print a, b, c
['world'] ['hello'] ['world']
这时a, c的值和地址均改变,但二者仍相同,b不改变。由于list的可变性,所以修改list的值不需要另外开辟空间,只需修改原地址的值。所以a, c均改变。
在了解了以上的不同点之后,我们就能很好地分析浅拷贝和深拷贝了。
我们均用list作为例子。
二、浅拷贝
>>> a = ['hello', [123, 234]]
>>> b = a[:]
>>> [id(x) for x in a,b]
[4496003656, 4496066752]
>>> [id(x) for x in a]
[4496091584, 4495947536]
>>> [id(x) for x in b]
[4496091584, 4495947536]
Line3,4可以看出a, b地址不同,这符合list是可变的,应开辟不同空间。那浅拷贝就是拷贝了一个副本吗?再看Line5 - 8,我们发现a, b中元素的地址是相同的。如果说字符串'hello'地址一致还能理解,但是第二个元素是list地址仍一致。 这就说明了浅拷贝的特点,只是将容器内的元素的地址复制了一份 。
接着我们尝试修改a, b中的值:
>>> a[0] = 'world'
>>> a[1].append(345)
>>> print 'a = ', a, '\n\r', 'b = ', b
a = ['world', [123, 234, 345]]
b = ['hello', [123, 234, 345]]
a中第一个元素str改变,但是b中未改变;a中第二个元素改变,b中也改变。这就符合不可变的对象修改会开辟新的空间,可变的对象修改不会开辟新空间。也进一步证明了 浅拷贝仅仅是复制了容器中元素的地址 。
三、深拷贝
>>> from copy import deepcopy
>>> a = ['hello', [123, 234]]
>>> b = deepcopy(a)
>>> [id(x) for x in a, b]
[4496066824, 4496066680]
>>> [id(x) for x in a]
[4496091584, 4496067040]
>>> [id(x) for x in b]
[4496091584, 4496371792]
深拷贝后,可以发现a, b地址以及a, b中元素地址均不同。这才是完全 拷贝了一个副本 。
修改a的值后:
>>> a[0] = 'world'
>>> a[1].append(345)
>>> print 'a = ', a, '\n\r', 'b = ', b
a = ['world', [123, 234, 345]]
b = ['hello', [123, 234]]
从Line4,5中可以发现仅仅a修改了,b没有任何修改。 因为b是一个完全的副本,元素地址均与a不同,a修改,b不受影响 。
总结:
1. 赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 )。
2. 浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素( 新瓶装旧酒 )。
3. 深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。也就是说( 新瓶装新酒 )。
【转】Python中的赋值、浅拷贝、深拷贝介绍的更多相关文章
- python 中的 赋值 浅拷贝 深拷贝
1.对象的赋值 都是进行对象引用(内存地址)传递,即 b is a ,a 变 b也变 2.浅拷贝 会创建一个新的对象,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址) 当我们使用下面的操作 ...
- Python中的赋值、深拷贝与浅拷贝(内存地址)
Python中的赋值.深拷贝与浅拷贝(内存地址) 1.python中的可变对象与不可变对象 (1) 可变对象:dict,list def dict_test(): a = {} b = a print ...
- Python中的赋值和拷贝
赋值 在python中,赋值就是建立一个对象的引用,而不是将对象存储为另一个副本.比如: >>> a=[1,2,3] >>> b=a >>> c= ...
- python中的“赋值与深浅拷贝”
Python中,赋值与拷贝(深/浅拷贝)之间是有差异的,这主要源于数据在内存中的存放问题,本文将对此加以探讨. 1 赋值(添加名字) 赋值不会改变内存中数据存放状态,比如在内存中存在一个名为data的 ...
- python中的赋值操作和复制操作
之前一直写C#,变量之间赋值相当于拷贝,修改拷贝变量不会改变原来的值.但是在python中发现赋值操作本质是和C++中的引用类似,即指向同一块内存空间.下面通过一个例子说明: p=[0,1,2,3,4 ...
- python中的赋值操作
参考:https://www.cnblogs.com/andywenzhi/p/7453374.html?tdsourcetag=s_pcqq_aiomsg(写的蛮好) python中的赋值操作“=” ...
- python中的赋值和深浅拷贝
python中,A object = B object 是一种赋值操作,赋的值不是一个对象在内存中的空间,而只是这个对象在内存中的位置 . 此时当B对象里面的内容发生更改的时候,A对象也自然而然的 ...
- (数据科学学习手札32)Python中re模块的详细介绍
一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...
- Python 中的赋值、拷贝、引用
在 python 中赋值语句总是建立对象的引用值,而不是复制对象.因此,python 变量更像是指针,而不是数据存储区域. 如图所示,当改变一个变量的值,另一个的值也会跟着改变.也就是浅拷贝. 若要实 ...
随机推荐
- ViewPager+Fragment实现页面的切换
新知识,新摘要: 效果图:framgent导入包都是v4包下,谨慎导入错误! 首先设置viewPager布局: <?xml version="1.0" encoding=&q ...
- 编程风格(Coding Style)要求
编程风格(Coding Style)要求2.1.1 文件(1) 每个模块(module)一般应存在于单独的源文件中,通常源文件名与所包含模块名相同.(2) 每个设计文件开头应包含如下注释内容:? 年份 ...
- Python中的range函数用法
函数原型:range(start, end, scan): 参数含义:start:计数从start开始.默认是从0开始.例如range(5)等价于range(0, 5); end:技术到end结束,但 ...
- js/jstl/el的区别
JavaScript 学习的路径:http://www.w3school.com.cn/js/js_intro.asp 是世界上最流行的编程语言. 这门语言可用于 HTML 和 web,更可广泛用于服 ...
- jquery动态删除html代码
1.remove() remove()方法移除被选元素,包括所有的文本和子节点. 语法:$(selector).remove() 当我们想将元素自身移除时我们用 .remove(),同时也会移除元素内 ...
- java : 包装类 缓冲机制的使用(转载)
摘要: 八种基本数据类型和其包装类中 Integer valueOf(int i).Byte valueOf(byte b).Short valueOf(short s).Long valueOf(l ...
- ANDROID调用webservice带soapheader验证
最近的一个项目中调用webservice接口,需要验证soapheader,现将解决方法记录如下:(网上资料出处太多,就不做引用,原作者如看到,如有必要添加请通知) 1.先看接口 POST /webs ...
- Thailand vs Soros
| exchange rate | | Thailand | Soros | |---------------+---------+----------+---------| | | orgin | ...
- (转载)持续集成(第二版)[来自:Martin Fowler]
转载自:iTech的博客 持续集成(第二版) 作者:Martin Fowler 译者:雷镇 持续集成 是一种软件开发实践.在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以 ...
- js替换选中的文字
替换html中选中的文字 function replaceSelection() { if (window.getSelection) { var selecter = window.getSelec ...