【发布时间】:2019-01-31 19:17:10
【问题描述】:
我一直在开发一个性能关键的应用程序,该应用程序需要经常复制二维整数列表并修改副本(我正在实现极小极大算法)。
我注意到在具有相同数量元素的列表上,副本和深度副本之间的性能存在巨大差异,我想了解我的想法是否正确。
要重现我的问题,请运行以下代码:
import numpy as np
np.random.seed(0)
lst1 = np.random.randint(100, size=1000 * 1000).tolist()
lst2 = np.random.randint(100, size=(1000, 1000)).tolist()
现在,对下面的语句进行计时,您应该会看到与我类似的计时。
%timeit copy.copy(lst1)
%timeit lst1.copy()
%timeit copy.deepcopy(lst2)
5 ms ± 49.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
5.47 ms ± 551 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.61 s ± 112 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
lst1 和 lst2 都有一百万个元素,但可靠地复制前者比具有相同数量元素的嵌套列表快 200 倍。我认为这与制作嵌套列表的深层副本可能需要一些缓慢的递归实现有关,所以我尝试了
%timeit copy.deepcopy(lst1)
1.43 s ± 90.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
而且时间仍然显示出大幅放缓。我检查了docs,但没有提供太多解释。然而,从时间上看,我怀疑deepcopy 也在复制每个 int,创建新的整数。但这似乎是一件很浪费的事情。
我的想法是对的吗? list.copy 和浅拷贝不在这里做什么 deepcopy?
我见过deepcopy() is extremely slow,但似乎这个问题是在寻求替代方案而不是解释(我不清楚)。
【问题讨论】:
-
这可能确实很浪费,但这就是
deepcopy所做的:它复制一切。它不知道你只想复制列表。 -
它不会复制所有内容(它不会复制不可变的内置类型),但它会检查所有内容并维护所有可见对象的缓存
-
谢谢你们的cmets,伙计们。请考虑充实它们作为答案。在我的代码中访问列表元素时,似乎我唯一的选择是切换到 1D 实现并实现一些逻辑以将 2D 索引转换为 1D 索引。
-
如果您确切地知道您的列表的形状,您可能可以实现自己的简单复制操作,即:
[sub.copy() for sub in nested_list]。这会更快
标签: python python-3.x copy deep-copy