[Python标准库]copy——复制对象
来源:互联网 发布:白百合离婚 知乎 编辑:程序博客网 时间:2024/05/17 00:58
[Python标准库]copy——复制对象
作用:提供一些函数,可以使用浅副本或深副本语义复制对象。
Python 版本:1.4 及以后版本
copy 模块包括两个函数 copy() 和 deepcopy(),用于复制现有的对象。
浅副本
copy() 创建的浅副本(shallow copy)是一个新容器,其中填充原对象内容的引用。建立 list 对象的一个浅副本时,会构造一个新的 list,并将原对象的元素追加到这个 list。
作用:提供一些函数,可以使用浅副本或深副本语义复制对象。
Python 版本:1.4 及以后版本
copy 模块包括两个函数 copy() 和 deepcopy(),用于复制现有的对象。
浅副本
copy() 创建的浅副本(shallow copy)是一个新容器,其中填充原对象内容的引用。建立 list 对象的一个浅副本时,会构造一个新的 list,并将原对象的元素追加到这个 list。
import copyclass MyClass: def __init__(self, name): self.name = name def __cmp__(self, other): return cmp(self.name, other.name)a = MyClass('a')my_list = [ a ]dup = copy.copy(my_list)print ' my_list:', my_listprint ' dup:', dupprint ' dup is my_list:', (dup is my_list)print ' dup == my_list:', (dup == my_list)print 'dup[0] is my_list[0]:', (dup[0] is my_list[0])print 'dup[0] == my_list[0]:', (dup[0] == my_list[0])
对于一个浅副本,不会复制 MyClass 实例,所以 dup 列表中的引用会指向 my_list 中相同的对象。
深副本
deepcopy() 创建的深副本是一个新容器,其中填充原对象内容的副本。要建立一个 list 的深副本,会构造一个新的 list,复制原列表的元素,然后将这些副本追加到新列表。
将前例中的 copy() 调用替换为 deepcopy(),可以清楚地看到输出的不同。
深副本
deepcopy() 创建的深副本是一个新容器,其中填充原对象内容的副本。要建立一个 list 的深副本,会构造一个新的 list,复制原列表的元素,然后将这些副本追加到新列表。
将前例中的 copy() 调用替换为 deepcopy(),可以清楚地看到输出的不同。
import copyclass MyClass: def __init__(self, name): self.name = name def __cmp__(self, other): return cmp(self.name, other.name)a = MyClass('a')my_list = [ a ]dup = copy.deepcopy(my_list)print ' my_list:', my_listprint ' dup:', dupprint ' dup is my_list:', (dup is my_list)print ' dup == my_list:', (dup == my_list)print 'dup[0] is my_list[0]:', (dup[0] is my_list[0])print 'dup[0] == my_list[0]:', (dup[0] == my_list[0])
定制复制行为
可以使用特殊方法 __copy__() 和 __deepcopy__() 来控制如何建立副本。
可以使用特殊方法 __copy__() 和 __deepcopy__() 来控制如何建立副本。
- 调用 __copy__() 而不提供任何参数,这会返回对象的一个浅副本。
- 调用 __deepcopy__(),并提供一个备忘字典,这会返回对象的一个深副本。所有需要深复制的成员属性都要连同备忘字典传递到 copy.deepcopy() 来控制递归。
下面这个例子展示了如何调用这些方法。
import copyclass MyClass: 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)
深副本中的递归
为了避免复制递归数据结构可能带来的问题,deepcopy() 使用了一个字典来跟踪已复制的对象。将这个字典传入 __deepcopy__() 方法,从而在该方法中也可以进行检查。
下面的例子显示了一个互连的数据结构(如一个有向图)可以通过实现 __deepcopy__() 方法帮助防止递归。
为了避免复制递归数据结构可能带来的问题,deepcopy() 使用了一个字典来跟踪已复制的对象。将这个字典传入 __deepcopy__() 方法,从而在该方法中也可以进行检查。
下面的例子显示了一个互连的数据结构(如一个有向图)可以通过实现 __deepcopy__() 方法帮助防止递归。
import copyimport pprintclass Graph: def __init__(self, name, connections): self.name = name self.connections = connections def add_connection(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_connection(copy.deepcopy(c, memo)) return duproot = Graph('root', [])a = Graph('a', [root])b = Graph('b', [a, root])root.add_connection(a)root.add_connection(b)dup = copy.deepcopy(root)
Graph 类包含一些基本的有向图方法。基于一个名和已连接的现有节点的一个列表可以初始化一个 Graph 实例。add_connection() 方法用于建立双向连接。deepcopy 也用到了这个方法。
__deepcopy__() 方法将打印消息来显示它如何得到调用,并根据需要管理备忘字典内容。它不是复制整个连接列表,而是创建一个新列表,把各个连接的副本追加到这个列表。这样可以确保复制各个新节点时会更新备忘字典,以避免递归问题或多余的节点副本。与前面一样,完成时会返回复制的对象。
上例中存在几个环,不过利用备忘字典处理递归就可以避免遍历导致栈溢出错误。复制根节点 root ,第二次遇到 root 节点时,此时正在复制 a 节点,__deepcopy__() 检测到递归,会重用备忘字典中现有的值,而不是创建一个新对象。
__deepcopy__() 方法将打印消息来显示它如何得到调用,并根据需要管理备忘字典内容。它不是复制整个连接列表,而是创建一个新列表,把各个连接的副本追加到这个列表。这样可以确保复制各个新节点时会更新备忘字典,以避免递归问题或多余的节点副本。与前面一样,完成时会返回复制的对象。
上例中存在几个环,不过利用备忘字典处理递归就可以避免遍历导致栈溢出错误。复制根节点 root ,第二次遇到 root 节点时,此时正在复制 a 节点,__deepcopy__() 检测到递归,会重用备忘字典中现有的值,而不是创建一个新对象。
0 0
- [Python标准库]copy——复制对象
- C++对象模型——对象复制语意学 (Object Copy Semantics)(第五章)
- Python--shutil--copy--复制文件
- Python的标准库sys、copy、os相关用法
- 复制构造器——Copy Constructor
- Python中的copy()方法为“浅复制”
- C++类对象的复制-拷贝构造函数——The c + + class object replication - copy constructor
- [Python标准库]weakref——对象的非永久引用
- OC基础——copy语法(Student属性的copy、Student对象的copy、Student子类对象的copy)
- C++标准库---copy()©_backward()
- 标准库举例:sys、copy
- python对象复制
- Python复制对象
- python复制对象
- python中的copy模块(浅复制和深复制)
- python中的copy模块(浅复制和深复制)
- python中的copy模块(浅复制和深复制)
- python 浅复制、深复制(copy/deepcopy)
- Android中Activity之间数据传递及返回
- ioctl() 函数用法
- Linux中查看文本文件内容命令cat/tac/nl/more/less/head/tail/vi总结
- Android-Selector实现EditText点击转变风格
- 数据库
- [Python标准库]copy——复制对象
- 修改Apache默认访问目录
- 《设计模式》读书笔记
- Day-6 休息日
- ThinkPad E450 小米无线Wifi成功驱动
- Java web war用法
- Android4.4中拒绝发送Intent.ACTION_MEDIA_MOUNTED扫描SD卡的广播 - Geder
- bzoj4027 贪心
- Spring Tool Suite插件的安装