如何创建与原始对象无关的Python对象副本?

3

(使用Python 2.7)

我正在尝试创建模板对象的副本以待填充。为简单起见,我尝试像这样做:

template={'thing1':'','thing2':'','thing3':''}
for number in some_list:
    pile[number]=template

但是后来当我这样做时:

pile[1]['thing1']='blahblah'

它还会导致:

print pile[2]['thing1']
'blahblah'
print template['thing1']
'blahblah'

我想要的是:
pile[1]['thing1']='blahblah'

让堆[2]保持不变,这样

print pile[2]['thing1']
''

我知道问题在于当我说

pile[number]=template

这意味着pile [1]是模板,而pile [2]也是模板。(我今天在处理这个问题时才完全意识到这一点...当我反复大声重复这个认识及其影响时,它慢慢地深入人心...这就是Python的工作方式,对吧?我感觉自己刚刚加入了Python俱乐部。我最初使用的是MATLAB,所以不要对我太苛刻。)

因此,我想可能有两种方法可以解决这个问题-一种涉及到一些不与原始对象链接的对象的复制,或者类似于这样的东西,并且可能非常简单和明显。也许还有另一种特定于字典的方法,例如初始化键之类的东西。我主要对第一种答案感兴趣,因为这将有助于完善我对Python工作方式的理解,但第二种答案也很好。谢谢:)

2个回答

4

制作字典的浅拷贝最简单的方法是使用字典的copy方法:

In [1]: template = {'thing1': '', 'thing2': '', 'thing3': ''}

In [2]: apile = template.copy()

In [3]: apile['thing1'] = 1

In [4]: apile
Out[4]: {'thing1': 1, 'thing2': '', 'thing3': ''}

In [5]: template
Out[5]: {'thing1': '', 'thing2': '', 'thing3': ''}

要制作一个列表的浅副本,您可以对整个列表进行切片:

copied_list = original_list[:]

如果您需要克隆其他对象,或者需要深度复制一个字典的字典(或字典列表,或其他可变对象),您应该使用 copy 模块:http://docs.python.org/2/library/copy.html
copy.copy(x)

返回x的浅拷贝。
copy.deepcopy(x)

返回x的深层拷贝。

浅拷贝和深拷贝之间的区别只与复合对象(包含其他对象的对象,如列表或类实例)有关:

  • 浅拷贝构造一个新的复合对象,然后(在可能的范围内)将对原始对象中找到的对象的引用插入其中。
  • 深拷贝构造一个新的复合对象,然后递归地将原始对象中找到的对象的副本插入其中。

 

关于您提到的第二种方法:确实,您可以从另一个字典创建一个字典,并且它将是一个副本:

In [23]: p = dict(template)

In [24]: p['thing1'] = 1

In [25]: template
Out[25]: {'thing1': '', 'thing2': '', 'thing3': ''}

In [26]: p
Out[26]: {'thing1': 1, 'thing2': '', 'thing3': ''}

太棒了。有一个名为“copy”的Python方法,可以复制字典。谢谢您,先生。文档也很有帮助。 - andy

3

这是我的初始解决方案

import copy

template = {1:''}
d = {}

for n in xrange(10):
    d[n] = copy.deepcopy(template)

然而,我更喜欢Pavel的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接