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. 【阿里云产品公测】云引擎ACE -discuz安装

    作者:阿里云用户云想未来 谢谢支持.为什么写的比较简单就是为方便新手谁想要很麻烦?亲测按这个教程可以安装成功!时间紧迫不发图片了纯原创 排版您请谅解 进入创建新应用的信息填写界面,此处需要填写一个赠送 ...

  2. Scoket

    1.Socket 几个常用的名词 IPC—>Inter Process Communication,进程间通信 socket —> 套接字 TCP—>Transmission Con ...

  3. 解决tsc.exe 已退出 代码为 1

    最近从ABP上面下载一个项目,然后用VS2015编译后报错,在Web项目下ABP---Framework---scripts下面多了一个abp.d.ts,报了一大堆错误 上网一查,d.ts是TypeS ...

  4. 【PHP基础】常用mySQL语句以及WampServer2.2设置数据库默认编码

    一.WampServer2.2设置数据库默认编码(此部分转自http://www.cnsecer.com/5984.html) wamp下MySQL的默认编码是Latin1,不支持中文,要支持中文的话 ...

  5. [CAMCOCO][C#]我的系统架构.服务器端.(四)----Model层 实体的自我验证

    这是Model的第二篇,上一篇点这里 这块完全是扒了@何镇汐大神博客里的教程实现的,在这之前完全没想到数据验证居然可以这样做!!在此表示严重感谢!!! 点击这里可以去了解这个方法的原理,老胡估计自己是 ...

  6. asp.net中用正则表达式验证数据格式

      这是一个验证是否为数字的例子: Regex reg   = new Regex(@"^[0-9]+\.{0,1}[0-9]*$");reg.IsMatch(textBox1.T ...

  7. MYSQL多实例配置与使用教程

    原文http://www.111cn.net/database/mysql/58651.htm 在实际的开发过程中,可能会需要在一台服务器上部署多个MYSQL实例,那建议使用MYSQL官方的解决方案 ...

  8. jquery对象与js对象的相互转换

    jQuery对象转成DOM对象: 两种转换方式将一个jQuery对象转换成DOM对象:[index]和.get(index); (1)jQuery对象是一个数据对象,可以通过[index]的方法,来得 ...

  9. ASP.NET C# 文件下载

    1.文件下载到客户端 //WriteFile实现下载 protected void Download_Click(object sender, EventArgs e) { string fileNa ...

  10. C# 上传图片前判断上传图片的宽和高

    网上找了好久没有找到... 最后百度到了这句话“由上传的HttpPostFile的InputStream创建一个Image对象,然后想怎么处置就随便你了”. HTML代码: <asp:FileU ...