我有一个小部件的树结构,例如集合包含模型,模型包含小部件。我想复制整个收藏,copy.deepcopy
与“pickle and de-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))
Timings:
>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 实现中),因为它是不太笼统比深度复制:许多对象可以深度复制但不能腌制。假设你的班级A
更改为...:
class A(object):
class B(object): pass
def __init__(self): self.b = self.B()
now, copy1
仍然工作得很好(A 的复杂性减慢了它的速度,但绝对不会阻止它);copy2
and 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
也就是说,pickle 总是假设类和函数是其模块中的顶级实体,因此“按名称”pickle 它们——深度复制绝对不会做出这样的假设。
因此,如果您遇到“某种深度复制”的速度绝对至关重要的情况,那么每一毫秒都很重要,并且您想利用您知道适用于您正在复制的对象的特殊限制,例如那些进行酸洗的对象适用的,或者喜欢其他形式的序列化和其他快捷方式的人,无论如何都可以继续 - 但如果你这样做,你必须意识到你正在限制你的系统永远受到这些限制,并非常清楚地记录设计决策和明确是为了未来维护者的利益。
对于正常情况,如果您想要通用性,请使用deepcopy
!-)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)