【Python】Python中的深浅拷贝
[转]python 复制(拷贝)对象 -- ::| 分类: Python |举报|字号 订阅 下载LOFTER我的照片书 |
需求: 你想复制一个对象.因为在Python中,无论你把对象做为参数传递,做为函数返回值,都是引用传递的. 讨论: 标准库中的copy模块提供了两个方法来实现拷贝.一个方法是copy,它返回和参数包含内容一样的对象. import copy
new_list = copy.copy(existing_list) 有些时候,你希望对象中的属性也被复制,可以使用deepcopy方法: import copy
new_list_of_dicts = copy.deepcopy(existing_list_of_dicts) 当你对一个对象赋值的时候(做为参数传递,或者做为返回值),Python和Java一样,总是传递原始对象的引用,而不是一个副本.其它一些语言当赋值的时候总是传递副本.Python从不猜测用户的需求 ,如果你想要一个副本,你必须显式的要求.
Python的行为很简单,迅速,而且一致.然而,如果你需要一个对象拷贝而并没有显式的写出来,会出现问题的,比如:
>>> a = [, , ]
>>> b = a
>>> b.append()
>>> print a, b
[, , , ] [, , , ]
在这里,变量a和b都指向同一个对象(一个列表),所以,一旦你修改了二者之一,另外一个也会受到影响.无论怎样,都会修改原来的对象.
注意:
要想成为一个Python高手,首先要注意的问题就是对象的变更操作和赋值,它们都是针对对象的引用操作的.一个语句比如a = []将a重新绑定给一个新对象,但不会影响以前的对象.然而,对象复制却不同,当对象复制后,对象变更操作就有了区别.
如 果你想修改一个对象,而且想让原始的对象不受影响,那你就需要对象复制.正如本节说的一样,你可以使用copy模块中的两个方法来实现需求.一般的,可以 使用copy.copy,它可以进行对象的浅复制(shallow copy),它复制了对象,但对于对象中的元素,依然使用引用.
浅复制,有时无法获得一个和原来对象完全一致的副本,如果你想修改对象中的元素,不仅仅是对象本身的话: >>> list_of_lists = [ ['a'], [, ], ['z', ] ]
>>> copy_lol = copy.copy(lists_of_lists)
>>> copy_lol[].append('boo')
>>> print list_of_lists, copy_lol
[['a'], [, , 'boo'], ['z', ]] [['a'], [, , 'boo'], ['z', ]] 在这里,变量list_of_lists,copy_lol指向了两个不同的对象,所以我们可以修改它们任何一个, 而不影响另外一个.然而,如果我们修改了一个对象中的元素,那么另一个也会受影响,因为它们中的元素还是共享引用.
如果你希望复制一个容器对象,以及它里面的所有元素(包含元素的子元素),使用copy.deepcopy,这个方法会消耗一些时间和空间,不过,如果你需要完全复制,这是唯一的方法.
对于一般的浅拷贝,使用copy.copy就可以了,当然,你需要了解你要拷贝的对象.要复制列表L,使用list(L),要复制一个字典d,使用dict(d),要复制一个集合s,使用set(s),这样,我们总结出一个规律,如果你要复制一个对象o,它属于内建的类型t,那么你可以使用t(o)来 获得一个拷贝.dict也提供了一个复制版本,dict.copy,这个和dict(d)是一样,我推荐你使用后者,这个使得代码更一致,而且还少几个字符.
要复制一个别的类型,无论是你自己写的还是使用库中的,使用copy.copy,如果你自己写一个类,没有必要费神去写clone和copy函数,如果你想定义自己的类复制的方式,实现一个__copy__,或者__getstate__和__setstate__.如果你想定义自己类型的deepcopy,实现方法__deepcopy__.
注意你不用复制不可修改对象(string,数字,元组),因为你不用担心修改它们.如果你想尝试一下复制,依然会得到原来的.虽然无伤大雅,不过真的浪费尽力: >>> s = 'cat'
>>> t = copy.copy(s)
>>> s is t
True is操作符用于不仅判断两个对象是否完全一致,而且是同一个对象(is判断标识符,要比较内容,使用==),判断标识符是否相等对于不可修改对象没有什么意义.然而 ,判断标识符对于可修改对象有时候是很重要的,比如,你不确定a和b是否指向同一个对象,使用a is b会立刻得到结果.这样你可以自己判断是否需要使用对象拷贝.
注意:
你可以使用另一种拷贝方式,给定一个列表L,无论是完整切片L[:]或者列表解析[x for x in L],都会获得L的浅拷贝,试试L+[],L*...但是上面两种方法都会使人迷惑,使用list(L)最清晰和快速,当然,由于历史原因,你可能会经常看到L[:]的写法.
对于dict,你可能见过下面的复制方法:
>>> for somekey in d:
... d1[somekey] = d[somekey] 或者更简单一些的方法,d1={},d1.update(d),无论怎样,这些代码都是缺乏效率的,使用d1=dict(d)吧. 相关说明: copy(x)
Shallow copy operation on arbitrary Python objects. See the module's __doc__ string for more info. deepcopy(x, memo=None, _nil=[])
Deep copy operation on arbitrary Python objects. See the module's __doc__ string for more info.
参考资料:
http://blog.163.com/sea_haitao/blog/static/7756216200921042345111/
【Python】Python中的深浅拷贝的更多相关文章
- 天啦噜!仅仅5张图,彻底搞懂Python中的深浅拷贝
Python中的深浅拷贝 在讲深浅拷贝之前,我们先重温一下 is 和==的区别. 在判断对象是否相等比较的时候我们可以用is 和 == is:比较两个对象的引用是否相同,即 它们的id 是否一样 == ...
- Python 中的深浅拷贝
Python 中的深浅拷贝 参考文献:https://blog.csdn.net/lnotime/article/details/81194633 参考文献:https://blog.csdn.net ...
- js中的深浅拷贝
js中的深浅拷贝 js中有深拷贝.浅拷贝一说,所谓的深浅拷贝是针对value类型为引用类型(函数.对象.数组)而言的,大概理解的就是: 浅拷贝: 拷贝出的对象c和原始对象o,c和o在key对应的val ...
- Python中的深浅拷贝
1.什么是深浅拷贝? python中一切皆对象,python中的数字.字符串.元组等,如果存放在了内存中,这部分内存里面的内容是不会改变的,但是也有情况,内存中存放了可变对象,比如说列表和字典,他们的 ...
- Core Python Programming一书中关于深浅拷贝的错误
该书关于深浅拷贝的论述: 6.20. *Copying Python Objects and Shallow and Deep Copies "when shallow copies are ...
- Python基础【3】:Python中的深浅拷贝解析
深浅拷贝 在研究Python的深浅拷贝区别前需要先弄清楚以下的一些基础概念: 变量--引用--对象(可变对象,不可变对象) 切片(序列化对象)--拷贝(深拷贝,浅拷贝) 我是铺垫~ 一.[变量--引用 ...
- 挖一挖python中的深浅拷贝问题
前几天在做面试题的时候,遇到一个与Python深浅拷贝的问题,今天总结出来一个方法,能够快速判断在对一个对象复制后,新对象与原来对象是否会互相影响的方法. 先抛出结论,然后我们对结论进行验证~~~ 先 ...
- 浅谈Python中的深浅拷贝的区别
深.浅拷贝总结 深拷贝 拷贝可变数据类型,如列表容器: a = [1, 2, [3, 4]] b = copy.deepcopy(a) a 与 b 所指的列表容器的空间地址不一致,即 id(a) != ...
- python学习笔记:深浅拷贝的使用和原理
在理解深浅拷贝之前,我们先熟悉下变量对象和数据类型 1.变量和对象 变量-引用-对象(可变对象,不可变对象) 在python中一切都是对象,比如[1,2],'hello world',123,{'k1 ...
- python之路(三)-深浅拷贝
深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝指拷贝数据集合的所有层.所 ...
随机推荐
- LaTeX算法排版 笔记
方式一 需要包含的 \usepackage[noend]{algpseudocode} \usepackage{algorithmicx,algorithm} 源码 \begin{algorithm} ...
- 【JAVAWEB学习笔记】网上商城实战4:订单模块
今日任务 完成订单模块的功能 1.1 订单 模块的功能 1.1.1 我的订单: [我的订单的查询] * 在header.jsp中点击我的订单. * 提交到Servlet: * 获得用户 ...
- 【Java】SpringBoot入门学习及基本使用
SpringBoot入门及基本使用 SpringBoot的介绍我就不多说了,核心的就是"约定大于配置",接下来直接上干货吧! 本文的实例: github-LPCloud,欢迎sta ...
- 获取token
获取token 提示:openstack 这个是获取N版的方法 ,主要区别在于这个路径上(http://192.168.0.228:35357/v3/auth/tokens ),以前版本可能会是v2 ...
- eclipse 的alt shift a,r 这个快捷键怎么操作 怎么按 eclipse 快捷键 逗号 什么意思
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha eclipse 的alt shift a,r 这个快捷键怎么操作 怎么按 eclipse ...
- [JOBDU1172]哈夫曼树
题目大意: 给你一堆权值,求这些权值建成哈夫曼树后的WPL. 思路: 哈夫曼树的WPL等于各非叶子结点权值之和. 所以直接贪心模拟构建哈夫曼树的过程. 先把所有的权值放在一个堆中,然后每次取里面最小的 ...
- Mybatis分页插件PageHelper的实现
Mybatis分页插件PageHelper的实现 前言 分页这个概念在做web网站的时候很多都会碰到 说它简单吧 其实也简单 小型的网站,完全可以自己写一个,首先查出数据库总条数,然后按照分页大小分为 ...
- 【转】_CrtSetBreakAlloc 内存泄漏
声明:本内容转载自 https://my.oschina.net/gp8wLHNUeKd2C/blog/110707 在使用VS开发过程中,(今日)遇到内存泄漏的情况.具体表现为: 在输出窗口中,显示 ...
- 编程经验(C#)
本文记录我在编程里学到的一些小技巧,遇到了就记录一下. 1.如果通用接口中的回调没有参数,而调用时需要参数,这个时候可以用匿名函数多封装一层.例如: Private void Main() { Fun ...
- mysql数据库文件简介和应用
存放目录: 用 whereis my.cnf 查看mysql配置文件的目录,查看my.cnf的datadir参数可找到mysql数据库文件的存放目录. 本机存放的目录为/var/lib/mysql,进 ...