Python中的赋值、浅拷贝、深拷贝介绍


Posted in Python onMarch 09, 2015

和很多语言一样,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获取Windows或Linux主机名称通用函数分享
Nov 22 Python
解析Python编程中的包结构
Oct 25 Python
【Python】Python的urllib模块、urllib2模块批量进行网页下载文件
Nov 19 Python
python selenium自动上传有赞单号的操作方法
Jul 05 Python
PyQt5使用QTimer实现电子时钟
Jul 29 Python
解决python 文本过滤和清理问题
Aug 28 Python
Pytorch在NLP中的简单应用详解
Jan 08 Python
Scrapy模拟登录赶集网的实现代码
Jul 07 Python
python 利用zmail库发送邮件
Sep 11 Python
Python实现Kerberos用户的增删改查操作
Dec 14 Python
python 实现的车牌识别项目
Jan 25 Python
python操作xlsx格式文件并读取
Jun 02 Python
Python自动连接ssh的方法
Mar 07 #Python
Python最长公共子串算法实例
Mar 07 #Python
Python复制目录结构脚本代码分享
Mar 06 #Python
python获取android设备的GPS信息脚本分享
Mar 06 #Python
Python写的英文字符大小写转换代码示例
Mar 06 #Python
Python脚本实现集群检测和管理功能
Mar 06 #Python
Python守护进程(daemon)代码实例
Mar 06 #Python
You might like
php数据库连接时容易出错的特殊符号问题
2010/09/01 PHP
使用PHP 5.0创建图形的巧妙方法
2010/10/12 PHP
php生成图片验证码的方法
2016/04/15 PHP
PHP分页初探 一个最简单的PHP分页代码的简单实现
2016/06/21 PHP
php+jQuery+Ajax简单实现页面异步刷新
2016/08/08 PHP
PHP 根据key 给二维数组分组
2016/12/09 PHP
PHP中类的自动加载的方法
2017/03/17 PHP
JS是否可以跨文件同时控制多个iframe页面的应用技巧
2007/12/16 Javascript
扩展javascript的Date方法实现代码(prototype)
2010/11/20 Javascript
表格奇偶行设置不同颜色的核心JS代码
2013/12/24 Javascript
JS实现不规则TAB选项卡效果代码
2015/09/16 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
JS仿JQuery选择器功能
2017/03/08 Javascript
jQuery+vue.js实现的九宫格拼图游戏完整实例【附源码下载】
2017/09/12 jQuery
解决Vue.js由于延时显示了{{message}}引用界面的问题
2018/08/25 Javascript
微信上传视频文件提示(推荐)
2018/11/22 Javascript
JavaScript实现打字游戏
2021/02/19 Javascript
常见的python正则用法实例讲解
2016/06/21 Python
解决安装tensorflow遇到无法卸载numpy 1.8.0rc1的问题
2018/06/13 Python
数据清洗--DataFrame中的空值处理方法
2018/07/03 Python
Python 使用类写装饰器的小技巧
2018/09/30 Python
Windows下安装Scrapy
2018/10/17 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
Python变量访问权限控制详解
2019/06/29 Python
Django基础知识 web框架的本质详解
2019/07/18 Python
浅谈Python3实现两个矩形的交并比(IoU)
2020/01/18 Python
python3发送request请求及查看返回结果实例
2020/04/30 Python
Python捕获异常堆栈信息的几种方法(小结)
2020/05/18 Python
SheIn俄罗斯:时尚女装网上商店
2017/02/28 全球购物
文秘专业毕业生就业推荐信
2013/11/08 职场文书
医学生职业生涯规划书范文
2014/03/13 职场文书
大学生毕业求职信
2014/06/12 职场文书
乡镇党的群众路线对照检查材料
2014/09/24 职场文书
html中显示特殊符号(附带特殊字符对应表)
2021/06/21 HTML / CSS
Mysql超详细讲解死锁问题的理解
2022/04/01 MySQL
Redis特殊数据类型bitmap位图
2022/06/01 Redis