每日一“酷”之copy
Copy – 复制对象
作用:提供一些函数,可以使用浅副本或深副本语义复制对象。
copy模块包括两个函数copy()和deepcopy(),用于复制现有的对象
1、 浅副本
copy()创建的浅副本(shallow copy)是一个新容器,其中填充原对象内容的引用。建立list对象的一个浅副本时,会构造一个新的list,并将原对象的元素追加到这个list。
import copy class MyClass(object):
def __init__(self,name):
self.name = name
def __cmp__(self,other):
return cmp(self.name,other.name) a = MyClass('a')
my_lt = [a]
dup = copy.copy(my_lt)
print ' my_lt:',my_lt
print ' dup:',dup
print ' dup is my_lt:',(dup is my_lt)
print ' dup == my_lt:',(dup == my_lt)
print 'dup[0] is my_lt[0]:',(dup[0] is my_lt[0])
print 'dup[0] == my_lt[0]:',(dup[0] == my_lt[0])
运行结果:
__cmp__() 在比较类实例时被调用
对于一个浅副本,不会复制Myclass实例,所以dup列表中的引用会指向my_lt中相同的对象
2、 深副本
deepcopy()创建的深副本是一个新的容器,其中填充源对象内容的副本.要建立一个list的深副本,会构成一个新的list,复制原列表的元素,然后将这些副本追加到新列表。
import copy class MyClass(object):
def __init__(self,name):
self.name = name
def __cmp__(self,other):
return cmp(self.name,other.name) a = MyClass('a')
my_lt = [a]
dup = copy.deepcopy(my_lt)
print ' my_lt:',my_lt
print ' dup:',dup
print ' dup is my_lt:',(dup is my_lt)
print ' dup == my_lt:',(dup == my_lt)
print 'dup[0] is my_lt[0]:',(dup[0] is my_lt[0])
print 'dup[0] == my_lt[0]:',(dup[0] == my_lt[0])
运行结果:

3、 定制复制行为
可以使用特殊方法__copy__() 和__deepcopy__()来控制如何建立副本。
·调用__copy__()而不提供任何参数,这会返回对象的一个浅副本。
·调用__deepcopy__(),并提供一个北方字典,这回返回对象的一个深副本。所有需要深复制的成员属性都要连同备忘字典传递到copy.deepcopy()来控制递归。
例如:
import copy class MyClass(object):
def __init__(self,name):
self.name = name
def __cmp__(self,other):
return cmp(self.name,other.name)
def __copy__(self):
print '__copy__()'
return MyClass(self.name)
def __deepcopy__(self,memo):
print '__deepcopy__(%s)' % str(memo)
return MyClass(copy.deepcopy(self.name, memo,)) a = MyClass('a')
sc = copy.copy(a)
dc = copy.deepcopy(a)
运行结果:
备忘字典用于跟踪已复制的值,以避免无限递归
4、 深副本中的递归
为了避免复制递归数据结构可能带来的问题,deepcopy()使用一个字典来跟踪已复制的对象。将这个歌字典传入__deepcopy__() 方法,从而在该方法中也可以进行检查。
下面的例子显示了一个互连的数据结构(如图1)可以通过实现__deepcopy__()方法帮助防止递归。

图1
class Graph(object):
def __init__(self,name,connections):
self.name = name
self.connections = connections
def add_connections(self,other):
self.connections.append(other)
def __repr__(self):
return 'Graph(name=%s,id=%s)' % (self.name,id(self))
def __deepcopy__(self,memo):
print '\nCalling __deepcopy__ for %r' % self
if self in memo:
existing = memo.get(self)
print ' Already copied to %r' % existing
return existing
print ' Memo dictionary'
pprint.pprint(memo,indent=4,width=40)
dup = Graph(copy.deepcopy(self.name, memo),[])
print ' Copying to new object %s' % dup
memo[self] = dup
for c in self.connections:
dup.add_connections(copy.deepcopy(c, memo))
return dup
root = Graph('root',[])
a = Graph('a',[root])
b = Graph('b',[a,root])
root.add_connections(a)
root.add_connections(b)
dup = copy.deepcopy(root)
Graph类包含一些基本的有向图方法。基于一个名和已连接的现有节点的一个列表可以初始化一个Graph实例。add_connection()方法用于建立双向谅解deepcopy也用到了这个方法__deepcopy__()方法将打印消息来显示它如何得到调用,
并根据需要管理备忘录字典内容。它不是复制整个链接列表,而是创建一个新的列表,把各个连接的副本追加到这个列表。这样可以确保复制各个新节点时会更新备忘录字典,以免递归问题或多余的节点副本。与前面一样,完成时会返回复制的对象。
如图1 中存在几个环,不过利用备忘录字典处理递归就可以避免遍历导致栈溢出错误。复制根节点root时,输入如下:
第二次遇到root节点时,此时正在复制a节点,__deepcopy__()检测到递归,会重用备忘录字典中现有的值,而不是创建一个新对象。
每日一“酷”之copy的更多相关文章
- 每日一“酷”之Cookie
Cookie---Http Cookie 作用:Cookie模块定义一些类来解析和创建HTTP cookie首部 Cookie模块为大多数符合RFC 2109的cookie实现一个解析器.这个实现没有 ...
- 每日一“酷”之Queue
Queue—线程安全的FIFO实现 作用:提供一个线程安全的FIFO实现 Queue模块提供了一个适用于多线程编程的先进先出(first-in,first-out)数据结构,可以用来在生产者和消费者线 ...
- 每日一“酷”之pprint
pprint – 美观打印 作用:美观打印数据结构 pprint 包含一个“美观打印机”,用于生成数据结构的一个美观视图.格式化工具会生成数据结构的一些表示,不仅可以由解释器正确地解析,而且便于人类阅 ...
- 每日一“酷”之heapq
作用:heapq模块实现一个适用于Python列表的最小堆排序算法 堆(heap)是一个属性数据结构,其中子节点与父节点是一种有序关系.二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全 ...
- 每日一“酷”之bisect
作用:维护有序列表,而不必在每次想列表增加一个元素时调用sort排序 bisect 模块实现了一个算法用于向列表中插入元素,同时仍保持列表有序.有些情况下,这比反复对一个了表序列更高效,另外也比构建一 ...
- 每日一“酷”之array
array--国定类型数据序列 array模块定义一个序列数据结构,看起来和list非常相似,只不过所有成员都必须是相同的基本类型. 1.初始化 array实例化时可以提高一个参数来描述允许哪个种数据 ...
- 每日一“酷”之difflib
介绍:difflib 比较序列.该模块包含一些用来计算和处理序列直接差异的工具.她对于比较文本尤其用,其中包含的函数可以使用多种常用差异格式生成报告. 测试数据(splitlines()按行划分为序列 ...
- 每日一“酷”之textwrap
介绍:需要美观打印时,可以使用textwrap模块来格式化要输出的文本,这个模块允许通过编程提高类似段落自动换行或填充特性等功能. 1 创建实例数据 sample_text = ''' I’m ver ...
- 每日一“酷”之string
介绍:string模块可以追溯到最早的Python版本中.现在很多的被移植为str和unicode对象的方法,在python3.0中会被完全去除.string模块中,有很多有用的常量和累,用来处理st ...
随机推荐
- 关于Django中的表单验证
ModelForm 和 普通的Form 都可以做表单验证 对于ModelForm如果只是想验证其中一部分model中的field,可以指定:内部类Meta的fields元素: fields = ('x ...
- JAX-WS开发WebService程序
近来公司里要用的到WebService做开发,所以就自己学习了一下,刚开始感觉挺难的,但是真正学会以后,原来这么简单. 今天把这些东西哦记下来,以便日后的复习. 我来介绍一下我的开发环境:Eclips ...
- Visual Studio 扩展包(.vsix)制作
前言:上篇介绍了 Visual Studio扩展工具添加与卸载,本编要介绍的是Visual Studio 扩展包(.vsix)的制作. 方法: ①.下载并安装Visual Studio 2010 SD ...
- php实现二路归并排序
$arr = [9, 43, 12, 0, 87, 1]; function merge_sort(&$arr){ _merge_sort($arr, $arr, 0, count($arr) ...
- [wordpress]根据自定义字段排序并根据自定义字段查询
Wordpress中,根据根据自定义字段排序和查询是通过WP_Query()方法 如根据 一个自定义的sort的数字字段从小到大进行排序 $args = array( 'post_type' => ...
- nodejs7-buffer
buffer:js在后台操作的必须用到二进制,buffer类就是用于帮助我们处理这种情况 创建buffer对象: new Buffer(size):创建buff对象,有length属性 buf.f ...
- ViewPager 可左右滑动和缩放的图片浏览
最近因为要做一个项目,需要使用到图片的浏览.我就自己在网上找了些资料,然后加以修改整理后出来一个demo,希望可以帮助到需要的人.同时这也是我第一个技术博客. 在做之前首先需要了解一下什么是ViewP ...
- (火炬)MS SQL Server数据库案例教程
(火炬)MS SQL Server数据库案例教程 创建数据库: CREATE DATABASE TDB //数据库名称 ON ( NAME=TDB_dat,//逻辑文件名 在创建数据库完成之后语句中引 ...
- Ajax Array Json 示例
function functionName(){ var list=new Array(); $("td.classA").each(function(){ list.push($ ...
- HTML+CSS学习笔记 (10) - CSS格式化排版
文字排版--字体 我们可以使用css样式为网页中的文字设置字体.字号.颜色等样式属性.下面我们来看一个例子,下面代码实现:为网页中的文字设置字体为宋体. body{font-family:" ...