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根据出生年份简单计算生肖的方法
Mar 27 Python
Java编程迭代地删除文件夹及其下的所有文件实例
Feb 10 Python
Python面向对象之静态属性、类方法与静态方法分析
Aug 24 Python
想学python 这5本书籍你必看!
Dec 11 Python
python石头剪刀布小游戏(三局两胜制)
Jan 20 Python
python读取图片任意范围区域
Jan 23 Python
浅谈Python中函数的定义及其调用方法
Jul 19 Python
python 3.8.3 安装配置图文教程
May 21 Python
matplotlib 画双轴子图无法显示x轴的解决方法
Jul 27 Python
Pycharm Available Package无法显示/安装包的问题Error Loading Package List解决
Sep 18 Python
PyQT5速成教程之Qt Designer介绍与入门
Nov 02 Python
Python爬虫入门案例之回车桌面壁纸网美女图片采集
Oct 16 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的一个基础知识 表单提交
2011/07/04 PHP
ThinkPHP框架实现session跨域问题的解决方法
2014/07/01 PHP
PHP YII框架开发小技巧之模型(models)中rules自定义验证规则
2015/11/16 PHP
PHP使用http_build_query()构造URL字符串的方法
2016/04/02 PHP
深入理解PHP原理之执行周期分析
2016/06/01 PHP
[原创]PHPCMS遭遇会员投稿审核无效的解决方法
2017/01/11 PHP
onkeyup,onkeydown和onkeypress的区别介绍
2013/10/21 Javascript
js简单实现根据身份证号码识别性别年龄生日
2013/11/29 Javascript
JavaScript代码编写中各种各样的坑和填坑方法
2014/06/06 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
JS+CSS实现淡入式焦点图片幻灯切换效果的方法
2015/02/26 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
2017/04/13 jQuery
微信小程序 获取二维码实例详解
2017/06/23 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
了解在JavaScript中将值转换为字符串的5种方法
2019/06/06 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
2019/07/10 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
JavaScript碰撞检测原理及其实现代码
2020/03/12 Javascript
jQuery 选择器用法实例分析【prev + next】
2020/05/22 jQuery
解决vue 退出动画无效的问题
2020/08/09 Javascript
Python去掉字符串中空格的方法
2014/03/11 Python
Python入门篇之字符串
2014/10/17 Python
Python SVM(支持向量机)实现方法完整示例
2018/06/19 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
Python爬取视频(其实是一篇福利)过程解析
2019/08/01 Python
opencv3/Python 稠密光流calcOpticalFlowFarneback详解
2019/12/11 Python
Django用户登录与注册系统的实现示例
2020/06/03 Python
Python轻量级web框架bottle使用方法解析
2020/06/13 Python
浅析python连接数据库的重要事项
2021/02/22 Python
CSS3 实现的缩略图悬停效果
2020/12/09 HTML / CSS
Nike比利时官网:Nike.com (BE)
2019/02/07 全球购物
高校教师岗位职责
2014/03/18 职场文书
家庭财产分割协议书范本
2014/11/24 职场文书
个人廉政承诺书
2015/04/28 职场文书
党支部半年考察意见
2015/06/01 职场文书
鸡毛信观后感
2015/06/11 职场文书