【问题标题】:copy.copy vs copy.deepcopy performance on tuples元组上的 copy.copy 与 copy.deepcopy 性能
【发布时间】:2012-05-03 12:13:01
【问题描述】:
%python -m timeit -s "import copy" "x = (1, 2, 3)" "copy.deepcopy(x)"
100000 loops, best of 3: 10.1 usec per loop

%python -m timeit -s "import copy" "x = (1, 2, 3)" "copy.copy(x)"
1000000 loops, best of 3: 0.609 usec per loop

为什么 deepcopycopy 慢 15 倍?

每个函数都必须遍历元组的元素。在该迭代期间,copy 为每个元素创建另一个引用; deepcopy 深度复制每个元素。

但是每个元素都是一个int,并且深度复制一个int 只会创建另一个对其的引用。换句话说,这两个函数似乎执行完全相同的步骤,执行相同的次数。

这是验证过程中没有创建新实例:

ActivePython 3.2.1.2 (ActiveState Software Inc.) based on
Python 3.2.1 (default, Jul 18 2011, 14:31:09) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> x = (1,2,3)
>>> import copy
>>> y = copy.copy(x)
>>> z = copy.deepcopy(x)
>>> x is y
True
>>> x is z
True
>>> x[1] is z[1]
True

【问题讨论】:

  • 不是一个真正的答案,而是一个怀疑:deepcopy 需要跟踪它已经复制了哪些元素以允许循环引用,这可能会增加一些开销,尤其是在这种简单的情况下。跨度>
  • 如果您可以滚动自己的“deepcopy”副本,那可能是值得的。我正在分析一些进化算法代码,它在 deepcopy 上花费了大量时间。我能够确定算法所需的约束并编写我自己的有限版本的 deepcopy,从而显着提高速度。您的里程可能会有所不同。

标签: python performance python-3.x copy deep-copy


【解决方案1】:

元组是不可变的,但它们可以包含可变元素:

>>> a = (1, 2, [])
>>> a[2].append(1000)
>>> a
(1, 2, [1000])

请注意,元组不会改变:它是列表。元组仍然包含完全相同的列表。

deepcopy 应该递归复制那些可变元素。 copy 只是复制对它们的引用。

>>> from copy import copy, deepcopy

>>> a = (1, 2, [])
>>> c = copy(a)
>>> d = deepcopy(a)

>>> a[2].append(1000)

>>> c
(1, 2, [1000])
>>> d
(1, 2, [])

【讨论】:

  • 是的,但是copydeepcopy 都需要遍历元组的元素。正如他们所做的那样,copy 为每个int 创建另一个引用,而deepcopy 复制int 实例。但是复制int 实例只会返回对同一实例的另一个引用。似乎这两个功能应该执行完全相同的步骤。我看不出这如何导致 15 倍的性能下降。
  • 我认为没有必要遍历元组进行浅拷贝。在不了解 Python 内部原理的情况下,我猜一个 memcpy 调用就足够了。
  • 你说得对,copy 不需要迭代。 Python 甚至不需要memcpy:它可以返回对原始元组的另一个引用!当然,这不适用于deepcopy
猜你喜欢
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 2014-06-19
  • 2014-10-25
  • 2013-11-12
  • 2018-03-03
相关资源
最近更新 更多