我有一个小部件的树结构,例如集合包含模型,模型包含小部件.我想复制整个集合,copy.deepcopy
与'pickle and de pickle'对象相比更快,但cPickle用C语言写得快得多,所以
为什么我(我们)总是不使用cPickle而不是深度复制?
还有其他副本吗?因为pickle比deepcopy慢,但cPickle更快,所以可能是深度复制的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
Alex Martell.. 32
问题是,pickle + unpickle可以更快(在C实现中),因为它不如深度复制一般:许多对象可以深度复制但不能腌制.例如,假设您的班级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: attribute lookup c.B failed
即,酸洗总是假设类和函数是其模块中的顶级实体,因此"按名称"腌制它们 - 深度复制绝对没有这样的假设.
因此,如果您遇到"有点深度复制"的速度绝对至关重要的情况,每毫秒都很重要,并且您希望利用您知道的特殊限制应用于您正在复制的对象,例如那些进行酸洗的对象通过各种方式适用或支持序列化和其他快捷方式的其他形式 - 但如果你这样做,你必须意识到你正在限制你的系统永远存在这些限制,并且非常清楚地记录设计决策,明确地为了未来的维护者的利益.
对于您需要通用性的NORMAL情况,请使用deepcopy
! - )
问题是,pickle + unpickle可以更快(在C实现中),因为它不如深度复制一般:许多对象可以深度复制但不能腌制.例如,假设您的班级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: attribute lookup c.B failed
即,酸洗总是假设类和函数是其模块中的顶级实体,因此"按名称"腌制它们 - 深度复制绝对没有这样的假设.
因此,如果您遇到"有点深度复制"的速度绝对至关重要的情况,每毫秒都很重要,并且您希望利用您知道的特殊限制应用于您正在复制的对象,例如那些进行酸洗的对象通过各种方式适用或支持序列化和其他快捷方式的其他形式 - 但如果你这样做,你必须意识到你正在限制你的系统永远存在这些限制,并且非常清楚地记录设计决策,明确地为了未来的维护者的利益.
对于您需要通用性的NORMAL情况,请使用deepcopy
! - )
您应该使用深度复制,因为它使您的代码更具可读性.使用序列化机制在内存中复制对象至少会让另一个阅读代码的开发人员感到困惑.使用深度复制还意味着您可以在深度复制中获得未来优化的好处.
优化的第一条规则:不要.