python复制库_Python3标准库:copy复制对象

1. copy复制对象

copy模块包括两个函数copy()和deepcopy(),用于复制现有的对象。

1.1 浅副本

copy()创建的浅副本(shallow copy)是一个新容器,其中填充了原对象内容的引用。建立list对象的一个浅副本时,会构造一个新的list,并将原对象的元素追加到这个list。

importcopyimportfunctools

@functools.total_orderingclassMyClass:def __init__(self, name):

self.name=namedef __eq__(self, other):return self.name ==other.namedef __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 ismy_list))print(‘dup == my_list:‘, (dup ==my_list))print(‘dup[0] is my_list[0]:‘, (dup[0] ismy_list[0]))print(‘dup[0] == my_list[0]:‘, (dup[0] == my_list[0]))

作为一个浅副本,并不会复制MyClass实例,所以dup列表中的引用会指向my_list中相同的对象。

1.2 深副本

deepcopy()创建的深副本是一个新容器,其中填充了原对象内容的副本。要建立一个list的深副本,会构造一个新的list,复制原列表的元素,然后将这些副本追加到新列表。

将前例中的copy()调用替换为deepcopy(),可以清楚地看出输出的不同。

importcopyimportfunctools

@functools.total_orderingclassMyClass:def __init__(self, name):

self.name=namedef __eq__(self, other):return self.name ==other.namedef __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 ismy_list))print(‘dup == my_list:‘, (dup ==my_list))print(‘dup[0] is my_list[0]:‘, (dup[0] ismy_list[0]))print(‘dup[0] == my_list[0]:‘, (dup[0] == my_list[0]))

列表的第一个元素不再是相同的对象引用,不过比较这两个对象时,仍认为它们是相等的。

1.3 定制复制行为

可以使用特殊方法__copy__()和__deepcopy__()来控制如何建立副本。

调用__copy__()而不提供任何参数,这会返回对象的一个浅副本。

调用__deepcopy__(),并提供一个备忘字典,这会返回对象的一个深副本。所有需要深复制的成员属性都要连同备忘字典传递到copy.deepcopy()以控制递归(备忘字典将在后面更详细地解释)。

importcopyimportfunctools

@functools.total_orderingclassMyClass:def __init__(self, name):

self.name=namedef __eq__(self, other):return self.name ==other.namedef __gt__(self, other):return self.name >other.namedef __copy__(self):print(‘__copy__()‘)returnMyClass(self.name)def __deepcopy__(self, memo):print(‘__deepcopy__({})‘.format(memo))returnMyClass(copy.deepcopy(self.name, memo))

a= MyClass(‘a‘)

sc=copy.copy(a)

dc= copy.deepcopy(a)

备忘字典用于跟踪已复制的值,以避免无限递归。

1.4 深副本中的递归

为了避免复制递归数据结构可能带来的问题,deepcopy()使用了一个字典来跟踪已复制的对象。将这个字典传入__deepcopy__()方法,这样在该方法中也可以检查这个字典。

importcopyclassGraph:def __init__(self, name, connections):

self.name=name

self.connections=connectionsdefadd_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 inmemo:

existing=memo.get(self)print(‘Already copied to {!r}‘.format(existing))returnexistingprint(‘Memo dictionary:‘)ifmemo:for k, v inmemo.items():print(‘{}: {}‘.format(k, v))else:print(‘(empty)‘)

dup=Graph(copy.deepcopy(self.name, memo), [])print(‘Copying to new object {}‘.format(dup))

memo[self]=dupfor c inself.connections:

dup.add_connection(copy.deepcopy(c, memo))returndup

root= 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__()方法将打印消息来显示这个方法是如何调用的,并根据需要管理备忘字典内容。它不是复制整个连接列表,而是创建一个新列表,再把各个连接的副本追加到这个列表。这样可以确保复制各个新节点时会更新备忘字典,而避免递归问题或多于的节点副本。与前面一页,完成时会返回复制的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值