复制.deepcopy还是创建新对象?

6
我正在开发实时应用程序,有时需要创建新的对象实例并始终具有相同的数据。
起初,我只是通过实例化它们来完成,但后来我意识到可能使用 copy.deepcopy 会更快。现在,我发现有人说 deepcopy 非常慢。
我无法简单地使用 copy.copy,因为我的对象中有列表。
我的问题是,你知道更快的方法吗?或者我只需要放弃并再次实例化它们?
感谢您的时间。

1
我在想,如果我只是在这些对象中添加一个“def copy(self):”,然后只是复制回这些对象内部的列表,会怎么样? - XNor
deepcopy 只是递归遍历结构并创建新实例。它能够智能地避免无限循环,并且可以进行定制,仅此而已。 - Martijn Pieters
所以 deepcopy 将检查所有列表值,以查看它们是否也需要复制; 创建新副本列表的 __copy__ 函数将有助于避免这种情况。 - Martijn Pieters
1个回答

4
我认为 copy.deepcopy() 仍然是纯 Python 的,所以不太可能带来任何速度提升。
我觉得这有点像一个经典的过早优化案例。我建议编写直观的代码,也就是简单地实例化每个对象。然后您可以对其进行分析并查看是否需要节省空间。在您的实际使用情况中,某些完全不同的代码可能会成为瓶颈。
编辑:我的原始答案中忘记提到一件事 - 如果要复制列表,请确保使用切片符号 (new_list = old_list [:]) 而不是在 Python 中对其进行迭代,因为后者比较慢。但是,这种方法不会进行深拷贝,因此如果您的列表有其他列表或字典,则需要使用 deepcopy()。对于 dict 对象,请使用 copy() 方法。
如果您仍然发现构造对象是耗时的,那么可以考虑如何加快速度。您可以尝试使用 __slots__,尽管它们通常是用于节省内存而不是 CPU 时间,因此我怀疑它们不会带来太多好处。在极端情况下,您可以将对象推送到 C 扩展模块中,这可能会更快,但复杂性会增加。这总是我过去采取的方法,在底层使用本机 C 数据结构,并使用 Python 的特殊方法在顶部包装“类似列表”或“类似字典”的接口。当然,这需要您乐意用 C 编写代码。
(顺带一提,除非有充分的理由,否则我会避免使用 C++,因为 C++ Python 扩展比纯 C 稍微麻烦一些,如果您有充分的动机,完全可以做到)
例如,如果您的对象具有非常长的列表,则可以考虑一种类似于按需复制的方法,其中对象的克隆只保留相同的引用而不是复制列表。每次访问它们时,您可以使用 sys.getrefcount() 来查看是否安全地进行原地更新,还是需要进行复制。这种方法很可能出错且过于复杂,但我想提一下以供参考。
您还可以查看对象层次结构,并查看是否可以将不需要复制的部分拆分为可在其他对象之间共享的部分。再次强调,重要的是,您首先要使代码正确,然后才能从实际使用情况了解最佳方法来使代码变快。

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