python - copy.deepcopy 与 pickle

标签 python pickle deep-copy

我有一个小部件的树形结构,例如集合包含模型,模型包含小部件。我想复制整个集合,copy.deepcopy 与“pickle 和去 pickle ”对象相比更快,但用 C 编写的 cPickle 更快,所以

  1. 为什么我(我们)不应该总是使用 cPickle 而不是 deepcopy?
  2. 还有其他的复制选择吗?因为 pickle 比 deepcopy 慢,但 cPickle 更快,所以 deepcopy 的 C 实现可能会是赢家

示例测试代码:

import copy
import pickle
import cPickle

class A(object): pass

d = {}
for i in range(1000):
    d[i] = A()

def copy1():
    return copy.deepcopy(d)

def copy2():
    return pickle.loads(pickle.dumps(d, -1))

def copy3():
    return cPickle.loads(cPickle.dumps(d, -1))

时间安排:

>python -m timeit -s "import c" "c.copy1()"
10 loops, best of 3: 46.3 msec per loop

>python -m timeit -s "import c" "c.copy2()"
10 loops, best of 3: 93.3 msec per loop

>python -m timeit -s "import c" "c.copy3()"
100 loops, best of 3: 17.1 msec per loop

最佳答案

问题是,pickle+unpickle 可以更快(在 C 实现中),因为它不如 deepcopy 通用:许多对象可以被深度复制但不能被 pickle 。例如,假设您的类 A 更改为...:

class A(object):
  class B(object): pass
  def __init__(self): self.b = self.B()

现在,copy1 仍然可以正常工作(A 的复杂性会减慢它的速度,但绝对不会阻止它); copy2copy3 中断,堆栈跟踪的末尾说...:

  File "./c.py", line 20, in copy3
    return cPickle.loads(cPickle.dumps(d, -1))
PicklingError: Can't pickle <class 'c.B'>: attribute lookup c.B failed

也就是说,pickling 总是假设类和函数是其模块中的顶级实体,因此“按名称”对它们进行 pickle——deepcopying 绝对不会做这样的假设。

因此,如果您遇到“有点深复制”的速度绝对至关重要的情况,那么每毫秒都很重要,并且您想利用您知道适用于您正在复制的对象的特殊限制,例如那些使 pickle 适用,或支持其他形式的序列化和其他快捷方式的方法,无论如何都要继续 - 但如果你这样做,你必须意识到你正在限制你的系统永远受这些限制,并记录该设计决策为了 future 的维护者的利益,非常清楚和明确。

对于需要通用性的 NORMAL 情况,请使用 deepcopy!-)

关于python - copy.deepcopy 与 pickle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1410615/

相关文章:

python - python 2.7 中的 pickle.dump 不保存类变量字典

.net - 深度复制PSObject

c++ - 如何对对象执行深拷贝?你如何制作复制构造函数?

对象图的 JavaScript 深拷贝

python - 为什么 google.protobuf 的导入在 ipython 中可以正常工作,但在 python 中却不行?

python - ValueError:输入 0 与层 conv2d_1 不兼容:预期 ndim=4,发现 ndim=3

python - 从 python 代码构建 exe 以避免 AV 误报的最佳方法

python - Visual Studio 的 PTVS 和 IronPython 工具有什么区别?

python - pickle OrderedDict 的子类

python - 用循环 pickle 图表