每日一“酷”之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 ...
随机推荐
- [经典算法] 字符串搜索Boyer-Moore
题目说明: 今日的一些高阶程式语言对于字串的处理支援越来越强大(例如Java.C#.Perl等),不过字串搜寻本身仍是个值得探讨的课题,在这边以Boyer- Moore法来说明如何进行字串说明,这个方 ...
- iOS - UI - UIStepper
7.UIStepper //计数器控件 固定宽高 UIStepper * stepper = [[UIStepper alloc] initWithFrame:CGRectMake(100, 10 ...
- 【转】Eclipse中一键调用javah生成jni的头文件
这里定义了一个本地方法jni_test,该方法返回一个String.其中System.loadLibrary是用来加载本地库的(dll或者so). 有了这个类以后,就可以调用javac命令编译,得到E ...
- mysql开启general log的方法
因为为了性能考虑,一般general log不会开启.slow log可以定位一些有性能问题的sql,而general log会记录所有的SQL. mysql5.0版本,如果要开启slow log.g ...
- Gulp 自动化的项目构建工具
在很多场合都会听到前端工和 node 程师推荐 Grunt 来实现项目的自动化,自动化可以自动完成 javascript/coffee/sass/less 等文件的的测试.检查.合并.压缩.格式化.部 ...
- React Native开发环境搭建
安装Xcode 安装Homebrew 安装Android SDK 安装flow和watchman 安装nodejs 安装react-native-cli 安装Genymotion 安装Webstorm ...
- 剑指Offer10 打印1到最大n位数
/************************************************************************* > File Name: 10_PrintT ...
- uva 12549 最大流
思路:这题的原型题是比较经典的网络流.原型题模型就是把所有的障碍去掉. 有障碍做法还是一样的,只用将每个列和行重新划分,求最大流就行了. #include <cstring> #inclu ...
- HTML插入SWF
1.插入透明flash代码 <object classid="clsid27CDB6E-AE6D-11cf-96B8-444553540000" codebase=" ...
- Bootstrap,导航栏点击效果修复(补)
前言: 昨天晚上休息,忘记发博客了.对于学习这件是,还是需要坚持的.想想自建一个Jekyll博客模版还是很兴奋的,话不多说,看正文吧! 关于开发: 先看个Demo吧,点这里.你会发现,点击是没有效果 ...