2016-09-13 3 views
3

Я пытался сохранить шаблон словаря в начале моего кода, что большинство функций будет использовать:Вложенные словари copy() или deepcopy()?

  • Словаря: ключи = имя клиента, значение = Dictionary2
  • Dictionary2: ключи = имя пользователя, значение = Нет

Я заполнил его всеми нашими клиентами и их пользователями. Затем каждая часть кода может копировать этот словарь и выводить его собственные. Цель состоит в том, что каждый вывод будет иметь ту же «базовую» структуру словаря, как шаблон, в котором None может быть изменен.

Для каждого процесса с помощью этого dictionnary я использую следующее:

process1dict = clientdict 
# processing 1 
output1dict = ... #modified version of original clientdict, the None values have been replaced by dictionaries/lists 

process2dict = clientdict 
# processing 2 
output2dict = ... #same here but could be different 

Проблема, что у меня есть, что cliendict изменяется каждый раз, когда он копируется в процессе! Я заметил, что из-за значения None в моем начальном cliendict он изменяется после каждого процесса (в зависимости от результата каждого из них).

Редактировать: Я нашел копию библиотеки, но copy(), похоже, не помогает моему делу. Я попробую deepcopy(), но почему copy() не сработал? И почему deepcopy() будет?

+1

Да, вам нужно сделать deepcopy -> без него 'clientdictDNT' просто указывает на один и тот же базовый словарь, поэтому он будет изменен при изменении' clientdict', вы также можете «dict (clientdict)» или «clientdict» .copy() ' – TemporalWolf

+1

Вы должны прочитать эту статью: [Факты и мифы о именах и значениях Python] (http://nedbatchelder.com/text/names.html) от SO veteran, Нед Батчелдер. –

+0

Если вы не используете deepcopy(), ваши члены ваших новых словарей будут указывать на словари, встроенные в ваш базовый словарь. Функция deepcopy() делает копии содержимого внутри скопированного словаря. –

ответ

3

Когда вы работаете с изменяемой коллекцией, как словарь или список, и выполняете присвоение, вы не создаете копию этого объекта по умолчанию - то есть присвоение некоторого dict b другому dict a создает ссылку от b к исходному объекту a, так что когда вы мутируете b, вы косвенно также мутируете a.

Смотрите этот базовый пример:

>>> orig = {"a": 1, "b": 2} 
>>> new = orig 
>>> new["a"] = 9 
>>> orig 
{'a': 9, 'b': 2} 
>>> new 
{'a': 9, 'b': 2} 
>>> new is orig 
True 

Чтобы это исправить и сохранить new и orig словари отдельные объекты, которые не ссылаются друг на друга, сделать deepcopy из orig при назначении его new:

>>> import copy 
>>> orig = {"a": 1, "b": 2} 
>>> new = copy.deepcopy(orig) 
>>> new["a"] = 9 
>>> orig 
{'a': 1, 'b': 2} 
>>> new 
{'a': 9, 'b': 2} 
>>> new is orig 
False 

Кроме того, здесь приведена ссылка tl; dr для документации по Python, приведенной выше:

Операторы присваивания в Python не копируют объекты, они создают привязки между объектом и объектом. Для коллекций, которые изменяются или содержат изменяемые элементы, иногда требуется копия, поэтому можно изменить одну копию, не изменяя другую.

+1

Во многих случаях глубокая копия не нужна и может нанести вред. Если у вас есть объект 'User (« Somebody »)', который принадлежит двум клиентам, вы, вероятно, НЕ хотите разделить их на два эквивалентных объекта и их мутировать отдельно. Если вам не нужна или нужна 'copy.deepcopy', вы можете использовать' dict.copy'. 'orig = {" a ": 1," b ": 2}; new = orig.copy() ' –

+1

В этом конкретном случае у меня нет объектов User Name, принадлежащих двум клиентам. Проблема, с которой я столкнулся сейчас, заключается в том, что этот «клиентский» словарь использовался как шаблон, а значение «Нет» использовалось как пустой символ, чтобы заполнить остальную часть словаря в процессах. Когда я впервые попытался использовать «copy()», который был в последнюю минуту написания вопроса, я узнал, что это не сработало, и я думаю, что понимаю, почему теперь благодаря вашим комментариям! Спасибо, ребята – Alex

+1

#upvote. Это было глубоко;) и полезно –

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