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模糊图片过滤的方法
Dec 14 Python
python 通过麦克风录音 生成wav文件的方法
Jan 09 Python
Python实现微信自动好友验证,自动回复,发送群聊链接方法
Feb 21 Python
Python实现的合并两个有序数组算法示例
Mar 04 Python
OpenCV搞定腾讯滑块验证码的实现代码
May 18 Python
python修改文件内容的3种方法详解
Nov 15 Python
Python Tornado批量上传图片并显示功能
Mar 26 Python
使用python批量转换文件编码为UTF-8的实现
Apr 03 Python
关于jupyter打开之后不能直接跳转到浏览器的解决方式
Apr 13 Python
简单了解Django项目应用创建过程
Jul 06 Python
Python Selenium自动化获取页面信息的方法
Aug 31 Python
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
Mar 29 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中的 inet_pton 网络函数
2019/12/16 PHP
accesskey 提交
2006/06/26 Javascript
一个对于Array的简单扩展
2006/10/03 Javascript
使用dynatrace-ajax跟踪JavaScript的性能
2010/04/12 Javascript
jQuery DOM操作实例
2014/03/05 Javascript
JS获取单击按钮单元格所在行的信息
2014/06/17 Javascript
JS中FRAME的操作问题实例分析
2014/10/21 Javascript
js禁止页面刷新与后退的方法
2015/06/08 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
2016/02/26 Javascript
JS文件上传神器bootstrap fileinput详解
2021/01/28 Javascript
微信小程序网络请求的封装与填坑之路
2017/04/01 Javascript
Angular4实现动态添加删除表单输入框功能
2017/08/11 Javascript
React Native之TextInput组件解析示例
2017/08/22 Javascript
详解RequireJs官方使用教程
2017/10/31 Javascript
解析Vue.js中的组件
2018/02/02 Javascript
Nodejs模块的调用操作实例分析
2018/12/25 NodeJs
Vue项目中使用jsonp抓取跨域数据的方法
2019/11/10 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
2020/02/15 Javascript
VUE使用axios调用后台API接口的方法
2020/08/03 Javascript
跟老齐学Python之类的细节
2014/10/13 Python
python处理按钮消息的实例详解
2017/07/11 Python
linecache模块加载和缓存文件内容详解
2018/01/11 Python
对python中两种列表元素去重函数性能的比较方法
2018/06/29 Python
python 实现对文件夹中的图像连续重命名方法
2018/10/25 Python
对Python使用mfcc的两种方式详解
2019/01/09 Python
python matplotlib库绘制散点图例题解析
2019/08/10 Python
Python实现随机爬山算法
2021/01/29 Python
特步官方商城:Xtep
2017/03/21 全球购物
希尔顿酒店官方网站:Hilton Hotels
2017/06/01 全球购物
全球最大的房车租赁市场:Outdoorsy
2018/09/19 全球购物
夏季奶茶店创业计划书
2014/01/16 职场文书
超市优秀员工事迹材料
2014/05/01 职场文书
2014年服务员个人工作总结
2014/12/23 职场文书
高校自主招生校长推荐信
2015/03/23 职场文书
保研推荐信格式
2015/03/25 职场文书
python3美化表格数据输出结果的实现代码
2021/04/14 Python