2009-05-08 2 views
19

мне было интересно в том, как делает именно DeepCopy работу в следующем контексте:словарь Python DeepCopy

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().

+1

ли вы напечатать два словаря, чтобы увидеть, если они отличаются? Что ты видел? Разве они были разными? Если это так, копия имеет новый список, к которому вы добавили элемент. –

ответ

15

documentation делает довольно понятным, что вы получаете новые копии, а не ссылки. Deepcopy создает глубокие копии для встроенных типов с различными исключениями и позволяет добавлять пользовательские операции копирования к вашим пользовательским объектам, чтобы получить поддержку для их глубокой копии. Если вы не уверены, хорошо, что это за модульное тестирование.

+0

Я не думаю, что он содержит встроенные типы, он утверждает, что он «копирует» выбираемые объекты ... Означает ли это, что я бы получил новую ссылку на список? – mandel

+7

У Deepcopy есть короткий список исключений. Все остальное копируется. «Этот модуль не копирует такие типы, как модуль, метод, трассировка стека, стек стека, файл, сокет, окно, массив или любые подобные типы». Вы получаете новый список. Не ссылка на список, а новый список. Распечатайте два словаря из вашего примера и посмотрите на них. –

2

Я знаю, что это не отвечает на ваш вопрос, но я думаю, что это примечательно для людей, которые смотрят на этот вопрос.

Если данные, которые вы копируете, являются простыми по своей природе, то глубококопий может быть излишним. С простыми в природе я имею в виду, если ваши данные представляются как 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) 

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 
+0

«С простыми в природе я имею в виду, если ваши данные представляются как Json» - это неправильный оператор: даже для простого, «JSON-способного» объекта может понадобиться '.deepcopy()', чтобы избежать ссылок. Попробуйте это: 'a = {1: 'A', 2: ['a', 'b', 'c'], 3: 'Z'}; b = a.copy(); а [2] .append ('d'); print b' – MestreLion

+0

Если данные представляются как JSON, почему бы просто не использовать 'json.loads (json.dumps (data))' ..? – rob

Смежные вопросы