Python字典深拷贝

21 投票
2 回答
30142 浏览
提问于 2025-04-15 11:27

我在想,深拷贝在以下情况下到底是怎么工作的:

from copy import deepcopy

def copyExample:
    self.myDict = {}
    firstPosition = "First"
    firstPositionContent = ["first", "primero"]
    secondPosition = "Second"
    secondPositionContent = ["second"]
    self.myDict[firstPosition] = firstPositionContent 
    self.myDict[secondPosition] = secondPositionContent
    return deepcopy(self.myDict)

def addExample(self):
    copy =  self.copyExample()
    copy["Second"].add("segundo")

它是返回我字典里列表的引用吗?还是说它像我预期的那样,把每个列表都复制到一个新的列表中,并且有不同的引用?

我知道什么是深拷贝(所以不需要解释深拷贝和浅拷贝的区别),但我想知道它是否像我想的那样工作,因此在我使用addExample()的时候不会改变实例变量。

2 个回答

3

我知道这不是在回答你的问题,但我觉得这对查看这个问题的人来说很重要。

如果你要复制的数据比较简单,使用深拷贝可能有点多余。这里的“简单”是指你的数据可以用Json来表示。让我用代码来说明一下:

我使用了http://www.json-generator.com/来获取一些示例的json数据。

def deepCopyList(inp):
    for vl in inp:
        if isinstance(vl, list):
            yield list(deepCopyList(vl))
        elif isinstance(vl, dict):
            yield deepCopyDict(vl)
        else:
            yield vl

            
def deepCopyDict(inp):
    outp = inp.copy()
    for ky, vl in outp.iteritems():
        if isinstance(vl, dict):
            outp[ky] = deepCopyDict(vl)      
        elif isinstance(vl, list):
            outp[ky] = list(deepCopyList(vl))  
    return outp
    
def simpleDeepCopy(inp):
    if isinstance(inp, dict):
        return deepCopyDict(inp)
    elif isinstance(inp, list):
        return deepCopyList(inp)
    else:
        return inp

if __name__ == '__main__':
    import simplejson as json
    import time
    from copy import deepcopy
    fl = open('sample.json', 'r')
    sample = json.load(fl)
    start = time.time()
    for _ in xrange(10000):
        tmp = simpleDeepCopy(sample)
    end = time.time()
    print 'simpleDeepCopy: ' + str(end - start)
    start = time.time()
    for _ in xrange(10000):
        tmp = deepcopy(sample)
    end = time.time()
    print 'copy.deepcopy: ' + str(end - start)

输出结果:

simpleDeepCopy: 0.0132050514221
copy.deepcopy: 2.66142916679

simpleDeepCopy: 0.0128579139709
copy.deepcopy: 2.60736298561
16

这个文档说得很清楚,你得到的是新的副本,而不是引用。深拷贝(deepcopy)会为内置类型创建深层副本,虽然有一些例外情况。你还可以为自己定义的对象添加自定义的拷贝操作,这样也能支持深拷贝。如果你不确定,那就用单元测试来验证一下吧。

撰写回答