Python之copy模块的使用
copy模块的作用
copy模块包括两个函数copy()和deepcopy(),用于复制现有的对象。
copy():是浅复制,一个新容器,其中填充原来内存对象的引用,
建立list对象的一个浅复制时,会构造一个新的list,并将原对象的元素追加到这个list。
deepcopy():是深复制,一个新容器,复制原列表的元素,然后将这些副本追加到新的列表中。
1、浅复制
import copy import functools @functools.total_ordering class MyClass: def __init__(self, name): self.name = name def __eq__(self, other): return self.name == other.name def __gt__(self, other): return self.name > other.name a = MyClass('a') my_list = [a] dup = copy.copy(my_list) print(' my_list:', my_list) print(' dup:', dup) print(' 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]))
运行效果
my_list: [<__main__.MyClass object at 0x0000021F44E1ECC8>] dup: [<__main__.MyClass object at 0x0000021F44E1ECC8>] #这里的浅复制是指把内存地址指向该对象 dup is my_list: False dup == my_list: True dup[0] is my_list[0]: True dup[0] == my_list[0]: True
2、深复制
import copy import functools @functools.total_ordering class MyClass: def __init__(self, name): self.name = name def __eq__(self, other): return self.name == other.name def __gt__(self, other): return self.name > other.name a = MyClass('a') my_list = [a] dup = copy.deepcopy(my_list) print(' my_list:', my_list) print(' dup:', dup) print(' 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])) # 这里比较两个值是否相等
运行效果
my_list: [<__main__.MyClass object at 0x000002022FDFED08>] dup: [<__main__.MyClass object at 0x000002022FE902C8>] dup is my_list: False dup == my_list: True dup[0] is my_list[0]: False dup[0] == my_list[0]: True
3、自定义复制的行为
import copy import functools @functools.total_ordering class MyClass: def __init__(self, name): self.name = name def __eq__(self, other): return self.name == other.name def __gt__(self, other): return self.name > other.name def __copy__(self): print('__copy__()') return MyClass(self.name) def __deepcopy__(self, memo): print('__deepcopy__({})'.format(memo)) return MyClass(copy.deepcopy(self.name, memo)) a = MyClass('a') sc = copy.copy(a) dc = copy.deepcopy(a)
运行效果
__copy__() __deepcopy__({}) <__main__.MyClass object at 0x00000205300A1408> <__main__.MyClass object at 0x00000205300A1348>
4、深复制中的递归,为了避免复制递归数据结构可能带来的问题,deepcopy()使用了一个字典来跟踪已复制的对象。将这个字典传入__deepcopy__()方法,这样在该方法中也可以检查这个字典。
import copy class 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={}, id={})'.format( self.name, id(self)) def __deepcopy__(self, memo): print('\nCalling __deepcopy__ for {!r}'.format(self)) if self in memo: existing = memo.get(self) print(' Already copied to {!r}'.format(existing)) return existing print(' Memo dictionary:') if memo: for k, v in memo.items(): print(' {}: {}'.format(k, v)) else: print(' (empty)') dup = Graph(copy.deepcopy(self.name, memo), []) print(' Copying to new object {}'.format(dup)) memo[self] = dup for c in self.connections: dup.add_connection(copy.deepcopy(c, memo)) return dup root = Graph('root', []) a = Graph('a', [root]) b = Graph('b', [a, root]) root.add_connection(a) root.add_connection(b) dup = copy.deepcopy(root)
运行效果
Calling __deepcopy__ for Graph(name=root, id=2396903141256) Memo dictionary: (empty) Copying to new object Graph(name=root, id=2396902987016) Calling __deepcopy__ for Graph(name=a, id=2396903141192) Memo dictionary: Graph(name=root, id=2396903141256): Graph(name=root, id=2396902987016) Copying to new object Graph(name=a, id=2396902989320) Calling __deepcopy__ for Graph(name=root, id=2396903141256) Already copied to Graph(name=root, id=2396902987016) Calling __deepcopy__ for Graph(name=b, id=2396903141128) Memo dictionary: Graph(name=root, id=2396903141256): Graph(name=root, id=2396902987016) Graph(name=a, id=2396903141192): Graph(name=a, id=2396902989320) 2396903141256: Graph(name=root, id=2396902987016) 2396903146184: [Graph(name=root, id=2396903141256), Graph(name=a, id=2396903141192)] 2396903141192: Graph(name=a, id=2396902989320) Copying to new object Graph(name=b, id=2396902987208)