我有一个小部件的树形结构,例如集合包含模型,模型包含小部件。我想复制整个集合,copy.deepcopy
与“pickle 和去 pickle ”对象相比更快,但用 C 编写的 cPickle 更快,所以
- 为什么我(我们)不应该总是使用 cPickle 而不是 deepcopy?
- 还有其他的复制选择吗?因为 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 的复杂性会减慢它的速度,但绝对不会阻止它); copy2
和 copy3
中断,堆栈跟踪的末尾说...:
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/