Python对象的深拷贝和浅拷贝详解


Posted in Python onAugust 25, 2014

本文内容是在《Python核心编程2》上看到的,感觉很有用便写出来,给大家参考参考!

浅拷贝

首先我们使用两种方式来拷贝对象,一种是切片,另外一种是工厂方法。然后使用id函数来看看它们的标示符

# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

 

35217032

35227912

29943304

 
他们的id都不同,按照正常的判断,三个不同id的对象应该都是独立的。那么我们先给他们改改名看看
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

     

a[0] = 'lisi'

b[0] = 'zhangsan'

 

print a

print b

 

35217032

35227912

33547784

['lisi', ['age', 18]]

['zhangsan', ['age', 18]]

对象a与b分别赋予了不同的名字,下来我们来看看给a对象改一个年龄
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

     

a[0] = 'lisi'

b[0] = 'zhangsan'

 

print a

print b

 

a[1][1] = 25

 

print a

print b

 

35217032

35227912

29943304

['lisi', ['age', 18]]

['zhangsan', ['age', 18]]

['lisi', ['age', 25]]

['zhangsan', ['age', 25]]

细心的朋友应该看出来了,改变a[0]元素与b[0]元素都互不影响,为何改变a[1][1]的元素会影响b[1][1]的元素呢?
要解开这个问题,只有先了解深拷贝与浅拷贝。以上实例中,我们创建的a与b都是从obj对象的浅拷贝,obj中第一个元素是字符串属于不可变类型,第二个元素是列表属于可变类型。因此我们进行拷贝对象时,字符串被显示拷贝重新创建了一个字符串,而列表只是复制引用,所以改变列表的元素会影响所有引用对象。从下列的id值中,你就能看明白了
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

a[0] = 'lisi'

b[0] = 'zhangsan'

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

a[1][1] = 25

b[1][1] = 30

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

32564088 34496008

32564088 34496008

32564088 34496008

 

32564088 34496008

34574704 34496008

33970672 34496008

 

32564088 34496008

34574704 34496008

33970672 34496008

复制对象的时候,我们可以看到所有元素的id都一直,我们分别改变了a与b对象的第一个字符串元素,因为字符串是不可变对象,所以改变后等于新创建,于是a与b的第一个字符串元素id不一致。而a与b的第二个元素都是列表可变对象,所以无论修改任何一个id值都表示一个指针,始终影响其它引用对象的值。
因此也就为什么修改a对象的年龄会影响b对象的年龄值,或者修改b对象的年龄值也会影响a对象的年龄值,包括obj对象在内。

深拷贝

以上都是浅拷贝,那么我们希望拷贝的对象是独立的,修改时不要影响其它值,这种我们称为深拷贝。实现深拷贝我们需要引用一个copy模块,copy模块有两个函数可用,一个是copy浅拷贝;另一个是deepcopy深拷贝。

# encoding=UTF-8

import copy

obj = ['name',['age',18]]

a=copy.deepcopy(obj)

b=copy.deepcopy(obj)

 

for x in a,b:

    print id(x[0]),id(x[1])

print

 

a[1][1] = 25

b[1][1] = 30

 

print a

print b

 

33612664 35477256

33612664 35477640

 

['name', ['age', 25]]

['name', ['age', 30]]

使用深拷贝后,列表元素的id不一致,表示独立对象,修改任何一个列表元素的值都不会影响其它对象。

以下是几点拷贝操作的注意事项:
第一、非容器类型(比如数字、字符串和其它“院子”类型的对象,像代码、类型和range对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成。

第二、如果元祖变量只包含原子类型对象,对它的深拷贝将不会进行。
我们把上面的例子改成元祖,然后使用深拷贝试试

# encoding=UTF-8

import copy

obj = ['name',('age',18)]

a=copy.deepcopy(obj)

b=copy.deepcopy(obj)

 

for x in a,b:

    print id(x),id(x[1])

print

 

34703752 34693000

34756616 34693000
Python 相关文章推荐
用Python实现QQ游戏大家来找茬辅助工具
Sep 14 Python
python统计文本字符串里单词出现频率的方法
May 26 Python
TensorFlow利用saver保存和提取参数的实例
Jul 26 Python
对PyTorch torch.stack的实例讲解
Jul 30 Python
python创建文件时去掉非法字符的方法
Oct 31 Python
深入解析python中的实例方法、类方法和静态方法
Mar 11 Python
python设置环境变量的原因和方法
Jun 24 Python
Python小程序之在图片上加入数字的代码
Nov 26 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
Jan 08 Python
Python中 Global和Nonlocal的用法详解
Jan 20 Python
解决Tensorflow占用GPU显存问题
Feb 03 Python
Python项目打包成二进制的方法
Dec 30 Python
Python3实现连接SQLite数据库的方法
Aug 23 #Python
Python3实现生成随机密码的方法
Aug 23 #Python
Python实现Linux下守护进程的编写方法
Aug 22 #Python
Python实现远程调用MetaSploit的方法
Aug 22 #Python
Python解释执行原理分析
Aug 22 #Python
Python实现的石头剪子布代码分享
Aug 22 #Python
Python使用MD5加密字符串示例
Aug 22 #Python
You might like
php 随机数的产生、页面跳转、件读写、文件重命名、switch语句
2009/08/07 PHP
2007/12/23更新创意无限,简单实用(javascript log)
2007/12/24 Javascript
JavaScript随机排序(随即出牌)
2010/09/17 Javascript
JavaScript中的isXX系列是否继续使用的分析
2011/04/16 Javascript
ie下jquery.getJSON的缓存问题的处理方法
2013/03/29 Javascript
跟我学习javascript的prototype,getPrototypeOf和__proto__
2015/11/17 Javascript
jQuery Validate插件实现表单强大的验证功能
2015/12/18 Javascript
jquery插件之文字间歇自动向上滚动效果代码
2016/02/25 Javascript
JavaScript设计模式开发中组合模式的使用教程
2016/05/18 Javascript
JS实现控制文本框的内容
2016/07/10 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
深入理解requestAnimationFrame的动画循环
2016/09/20 Javascript
微信小程序 swiper组件详解及实例代码
2016/10/25 Javascript
Angular的MVC和作用域
2016/12/26 Javascript
Bootstrap3 模态框使用实例
2017/02/22 Javascript
基于LayUI分页和LayUI laypage分页的使用示例
2017/08/02 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
2018/08/28 jQuery
[03:10]超级美酒第四天 fy拉比克秀 大合集
2018/06/05 DOTA
python遍历数组的方法小结
2015/04/30 Python
深入理解python try异常处理机制
2016/06/01 Python
Python爬虫通过替换http request header来欺骗浏览器实现登录功能
2018/01/07 Python
使用Python实现画一个中国地图
2019/11/23 Python
pytorch:实现简单的GAN示例(MNIST数据集)
2020/01/10 Python
有关HTML5页面在iPhoneX适配问题
2017/11/13 HTML / CSS
Dockers美国官方网站:卡其裤、男士服装、鞋及配件
2016/11/22 全球购物
俄罗斯领先的移动和数字设备在线商店:Svyaznoy.ru
2020/12/21 全球购物
用友笔试题目
2016/10/25 面试题
2014大学生批评与自我批评思想汇报
2014/09/21 职场文书
2014年乡镇卫生院工作总结
2014/11/24 职场文书
2014年林业工作总结
2014/12/05 职场文书
申报优秀教师材料
2014/12/16 职场文书
钱学森电影观后感
2015/06/04 职场文书
百家讲坛观后感
2015/06/12 职场文书
合理化建议书范文
2015/09/14 职场文书
springboot layui hutool Excel导入的实现
2022/03/31 Java/Android
python运算符之与用户交互
2022/04/13 Python