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的更多相关文章

  1. 每日一“酷”之Cookie

    Cookie---Http Cookie 作用:Cookie模块定义一些类来解析和创建HTTP cookie首部 Cookie模块为大多数符合RFC 2109的cookie实现一个解析器.这个实现没有 ...

  2. 每日一“酷”之Queue

    Queue—线程安全的FIFO实现 作用:提供一个线程安全的FIFO实现 Queue模块提供了一个适用于多线程编程的先进先出(first-in,first-out)数据结构,可以用来在生产者和消费者线 ...

  3. 每日一“酷”之pprint

    pprint – 美观打印 作用:美观打印数据结构 pprint 包含一个“美观打印机”,用于生成数据结构的一个美观视图.格式化工具会生成数据结构的一些表示,不仅可以由解释器正确地解析,而且便于人类阅 ...

  4. 每日一“酷”之heapq

    作用:heapq模块实现一个适用于Python列表的最小堆排序算法 堆(heap)是一个属性数据结构,其中子节点与父节点是一种有序关系.二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全 ...

  5. 每日一“酷”之bisect

    作用:维护有序列表,而不必在每次想列表增加一个元素时调用sort排序 bisect 模块实现了一个算法用于向列表中插入元素,同时仍保持列表有序.有些情况下,这比反复对一个了表序列更高效,另外也比构建一 ...

  6. 每日一“酷”之array

    array--国定类型数据序列 array模块定义一个序列数据结构,看起来和list非常相似,只不过所有成员都必须是相同的基本类型. 1.初始化 array实例化时可以提高一个参数来描述允许哪个种数据 ...

  7. 每日一“酷”之difflib

    介绍:difflib 比较序列.该模块包含一些用来计算和处理序列直接差异的工具.她对于比较文本尤其用,其中包含的函数可以使用多种常用差异格式生成报告. 测试数据(splitlines()按行划分为序列 ...

  8. 每日一“酷”之textwrap

    介绍:需要美观打印时,可以使用textwrap模块来格式化要输出的文本,这个模块允许通过编程提高类似段落自动换行或填充特性等功能. 1 创建实例数据 sample_text = ''' I’m ver ...

  9. 每日一“酷”之string

    介绍:string模块可以追溯到最早的Python版本中.现在很多的被移植为str和unicode对象的方法,在python3.0中会被完全去除.string模块中,有很多有用的常量和累,用来处理st ...

随机推荐

  1. 使用 xcode 8 构建版本 iTunes Connect 获取不到应用程序的状态

    今天在提交 APP 审核版本的时候iTunes Connect 一直获取不到应用程序的状态,原因是,14号 xcode 8一出 直接升级使用 xcode 8 打包发布包,然后直接用 xcode8 构建 ...

  2. linux_memcached_memcachedb

    三个区别 当你听到memcache与memcached时把它当做是一个东东就好了,尽管它们存在区别,但是这并不影响你对它们的运用及理解. “Memcache”它是一个自由和开放源代码.高性能.分配的内 ...

  3. seajs第一节,seajs基本使用

    什么是seajs,它是干什么使用的,可以去网上搜索一下, 官网:http://seajs.org/docs/ 基本使用seajs <!DOCTYPE html> <html> ...

  4. CF 335B - Palindrome 区间DP

    335B - Palindrome 题目: 给出一个字符串(均有小写字母组成),如果有长度为100的回文子串,输出该子串.否则输出最长的回文子串. 分析: 虽然输入串的长度比较长,但是如果存在单个字母 ...

  5. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  6. Linux apache日志分析常用命令汇总

    1.查看当天有多少个IP访问: awk '{print $1}' log_file|sort|uniq|wc –l 2.查看某一个页面被访问的次数: grep "/index.php&quo ...

  7. css中常用的几种居中方法

    在前端面试中,大都会问你div居中的方法: 文笔不好,就随便寥寥几句话概括了, 不过以后文笔肯定会变得更好一些的. 今天我们就细数一下几种方法: 1,使用position:absolute,设置lef ...

  8. CSS其他

    1.元素的宽度由内容撑开 display:inline;——不支持高度 display:inline-block;——在IE6下,不支持块标签 float position:absolute——每项设 ...

  9. AspxGridView ComboBoxComlum列数据联动

    第1步: 页面放置AspxGridView控件, 设置列ComboBox1, ComboBox2列, 拟通过ComboBox1列更新联动ComboBox2列. 两个数据列均为"ComboBo ...

  10. CSS之text-stroke

    啧啧啧( ̄︶ ̄),国庆人太多,所以假期还没结束就提前几天回来了.今天也是挤火车赶回来的,被夹在门里好尴尬啊~~ 回家的这几天在外婆家招待过的好爽啊,又是鱼又是肉,馋的我都不想走了. 然而自己在家只能“ ...