我有一个小部件的树状结构,例如集合包含模型,模型包含小部件。我想复制整个集合,与对对象进行“刺穿和去刺穿”相比,copy.deepcopy更快,但是cPickle因为用C语言编写要快得多,所以

  • 为什么我(我们)不总是使用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通用:许多对象可以被深度复制但不能被酸洗。例如,假设您的类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
    

    也就是说,酸洗总是假定类和函数是其模块中的顶级实体,因此,“按名称”对它们进行酸洗-深度复制绝对没有这样的假设。

    因此,如果您遇到“某种程度的深度复制”速度绝对至关重要的情况,那么每一毫秒都很重要,并且您想利用您知道要应用于复制对象的特殊限制,例如进行酸洗的那些适用的方法,或赞成其他形式的序列化和其他快捷方式的方法,请务必继续进行-但是,如果您这样做,则必须意识到您将使系统永远受限于这些限制,并非常清楚地记录该设计决策,并明确地为 future 维护者的利益。

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

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

    10-12 05:16