【问题标题】:How to deep copy duplicate a list of dictionaries?如何深拷贝复制字典列表?
【发布时间】:2019-08-28 16:52:00
【问题描述】:

我有一个字典列表:

my_list = [
  {
    'key1': 'value1',
  },
  {
    'key2': 'value2',
  },
]

我想像这样将列表相乘:

my_new_list = [
  {
    'key1': 'value1',
  },
  {
    'key2': 'value2',
  },
  {
    'key1': 'value1',
  },
  {
    'key2': 'value2',
  },
]

我尝试了my_list * 2 方法,但它会创建浅拷贝,这意味着如果我修改一个字典,它最终会修改列表中的许多其他字典。我想我正在寻找一个深层副本。

我也试过这个:

my_new_list = [my_list[i % len(my_list)] for i in range(4)]

但同样的问题。

这种方法有效,但对我来说感觉不是很pythonic,这就是为什么我正在寻找更好的答案。

from copy import deepcopy

my_new_list = [deepcopy(my_list[i % len(my_list)]) for i in range(4)]

如何创建这个深拷贝乘数列表?

【问题讨论】:

  • 怎么样 my_new_list = deepcopy(my_list) + deepcopy(my_list) 使用 deepcopy,并给出您要求的顺序。

标签: python deep-copy


【解决方案1】:

假设您的字典像示例中的字典一样浅,您可以使用 dict.copy() 的乘法方法。

l = [{'k1': 'v1'}, {'k2': 'v2'}]

result = [d.copy() for d in l * 2]
result[0]['k1'] = 'changed'
print(result)
# [{'k1': 'changed'}, {'k2': 'v2'}, {'k1': 'v1'}, {'k2': 'v2'}]

【讨论】:

  • 您仍然需要进行深度复制,因为我们不知道这些 dicts 中的真正内容,但除此之外这可行,并且可能会更好,因为它使用列表理解构建新列表。跨度>
  • @KennyOstrom - 好评。在答案中添加了对此效果的注释,以避免读者混淆。
【解决方案2】:

您可以使用复制模块进行深度复制, 试试这个

import copy
my_list = [{'key1': 'value1',},{'key2': 'value2',},]
my_list = my_list + copy.deepcopy(my_list)
my_list[0]['key1'] = 'next'
print(my_list)

【讨论】:

  • 好吧,你没有
【解决方案3】:

只需使用dict.copy() 方法制作dict 对象的文字副本。

my_new_list = [my_list[i % len(my_list)].copy() for i in range(len(my_list) * 2)]

现在来验证让我们更改第一个 dict 对象的值,

my_new_list[0]['key1'] = 'value3'
print(my_new_list)

输出:

[{'key1': 'value3'}, {'key2': 'value2'}, {'key1': 'value1'}, {'key2': 'value2'}]

【讨论】:

  • 这可能很危险。我们不知道所有的 dicts 对于浅拷贝都是安全的,只是 OP 中提供的那些。我很确定“pythonic”问题是在谈论使用模算术技巧(我个人对此很好,就像大多数人一样),而不是关于使用 python 附带的库是否是“pythonic”
【解决方案4】:

这个怎么样?对我来说似乎非常 pythonic...

my_list.extend(deepcopy(my_list))

这当然会覆盖my_list。如果你想保留它,只需提前将my_list 深度复制到my_new_list (或将my_list 的两个深度复制相加)。

这种方式应该适用于任何对象(可以深度复制),而不是依赖于dict 定义的行为

【讨论】:

    【解决方案5】:

    我很困惑为什么原始发帖人的解决方案被认为是“不是 Python 的”。你真的需要一个理由来贴上这个标签。但是看看他们的模算术答案,我猜这不仅仅是将列表加倍,而是将其用作重复模板以将新列表填充到任意大小。

    from copy import deepcopy
    from itertools import islice, cycle
    def fill(iterable, size):
        return map(deepcopy, islice(cycle(iterable), size))
    
    print (list(fill(my_list, 4)))
    

    itertools.cycle 为您提供重复行为
    itertools.islice 允许您指定元素的数量
    deepcopy 是为了可重用性,以防个别 dicts 的内部数据在浅拷贝中可能不安全(与发布的示例不同)——并且因为它在问题标题中。
    map 让我返回一个可迭代的 deepcopy 结果,所以如果你想要一个列表,你可以拥有它,但你可以随心所欲地使用它。

    郑重声明,我对模算术解决方案很满意。数学在 python 中仍然有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-24
      • 2013-04-06
      • 1970-01-01
      • 2017-06-29
      • 1970-01-01
      • 2013-07-26
      相关资源
      最近更新 更多