将一个 Python 字典复制 N 次到一个列表中

4
假设我有一个字典和以下列表:
l: list = [1,2,3,4]
d: dict = {"Hello": "World"}

我想精确复制这个字典len(l)次。

最终我想创建一个元组列表,它看起来像:

[(1, {"Hello": "World"}),(2, {"Hello": "World"}),(3, {"Hello": "World"}),(4, {"Hello": "World"})]

为了创建这个,我可以这样做:
output: list = list(zip(l, repeated_dicts))

但需要将字典在列表中复制指定次数。

我尝试使用itertools.isliceitertools.cycle,但是无法完全实现。有什么想法吗?


2
也许,这里最重要的问题是您是否打算修改这些字典,以及这些更改是否应反映在所有副本中。 - Marat
1
@Marat 很好的观点。实际上,我只是将它们用作多进程池的查找。例如,每个元组的第一个元素将是参数,第二个元素可能是例如 Web API 调用的标头。 - Coldchain9
5个回答

3

鉴于这些字典从不被修改,因此复制/深度复制是不必要的。最简单的方法(同时也是开销最小的方法)是:

output = [(i, d) for i in l]

1
@Coldchain9 使用其他答案已经解释过的相同对象可能存在潜在危险。如果在您的情况下确实没有关系,那么很好,但是如果您甚至没有意识到这个问题或者不理解它(正如您的评论问题所示),那么这种无知在其他情况下仍然可能会对您造成影响。 - Kelly Bundy
@KellyBundy 我是“有意无知”的,因为在我的使用情况下这些字典不会改变。我只需要它们作为标题输入到并行处理中。不过,我很感谢你的评论。 - Coldchain9
@Coldchain9 哦,好的,我现在有点明白你(未显示)的用法了。顺便说一下,其他人复制字典的原因是...因为你要求他们这样做。你标题中的第一个单词就是“复制”,并且你在问题中也重复了它。 - Kelly Bundy
请查看此链接:https://www.mycompiler.io/view/JgeW9FySeSm - Jupri
1
@Jupri 是的,这是预期的行为。正如在问题的评论中讨论的那样,不应该修改字典。答案中也明确说明:“鉴于这些字典永远不会被修改,…” - Marat
显示剩余3条评论

3
你正在寻找itertools.repeat()
创建一个可以无限次返回对象的迭代器。除非指定了times参数,否则会一直运行。
请注意,itertools.repeat()返回的字典将共享同一内存;对一个字典所做的更改将在列表的所有元素之间共享。这可能会导致一些相当困惑的行为
为了避免这种情况,您可以使用map()copy.copy()(如果字典中的所有内容都是不可变的)或copy.deepcopy()来确保每个字典的内存是独立的:
from itertools import repeat
from copy import copy

lst = [1, 2, 3, 4]
d = {"Hello": "World"}

list(zip(lst, map(copy, repeat(d))))

这将输出:
[
 (1, {'Hello': 'World'}), (2, {'Hello': 'World'}),
 (3, {'Hello': 'World'}), (4, {'Hello': 'World'})
]

注意,如果修改原始字典,则结果中的所有实例也会改变。 - Jan Wilamowski
@JanWilamowski 没错!刚刚编辑了。 :) - BrokenBenchmark

3

如果您需要执行实际的复制操作,不能简单地使用相同的d N次,否则列表的所有元素都将引用同一个对象(并且修改其中任何一个元素都会修改所有元素)。

在您的示例中,使用生成器表达式的.copy()方法应该就足够了:

l = [1,2,3,4]
d = {"Hello": "World"}
output = list((x, d.copy()) for x in l)

如果字典中还包含其他复杂对象,比如集合/列表/类/字典等,则需要使用copy.deepcopy

from copy import deepcopy

output = list((x, deepcopy(d)) for x in l)

1

在你的示例中,似乎只复制了字典一次。也许你可以使用带有元组的列表推导式?

l = [1, 1, 1]
d = {"Hello": "World"}

output = [(i, d.copy()) for i in range(1, len(l)+1)]

>>> output
[(1, {'Hello': 'World'}), (2, {'Hello': 'World'}), (3, {'Hello': 'World'})]

或对于列表中的每个数字:

>>> l = [1, 1, 1]
>>> [(i, d.copy()) for i in l]
[(1, {'Hello': 'World'}), (1, {'Hello': 'World'}), (1, {'Hello': 'World'})]

或者将列表复制i次:

>>> l = [1, 2, 1]
>>> [(i, [d.copy() for j in range(i)]) for i in l]
[(1, [{'Hello': 'World'}]),
 (2, [{'Hello': 'World'}, {'Hello': 'World'}]),
 (1, [{'Hello': 'World'}])]

1
 l: list = [1,2,3,4]
 d: dict = {"Hello": "World"}
 res = []
 for num in l:
   res.append((num, d.copy()))


>>>(res)
[(1, {'hello': 'World'}), (2, {'hello': 'World'}), (3, {'hello': 'World'})]

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