Как скопировать словарь и редактировать только копию - PullRequest
667 голосов
/ 18 марта 2010

Может кто-нибудь, пожалуйста, объясните мне это? Это не имеет никакого смысла для меня.

Я копирую словарь в другой и редактирую второй, и оба меняются. Почему это происходит?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}

Ответы [ 19 ]

718 голосов
/ 18 марта 2010

Python никогда неявно копирует объекты.Когда вы устанавливаете dict2 = dict1, вы заставляете их ссылаться на один и тот же точный объект dict, поэтому при его изменении все ссылки на него продолжают ссылаться на объект в его текущем состоянии.

Если вы хотите скопироватьдикт (что редко), вы должны сделать это явно с

dict2 = dict(dict1)

или

dict2 = dict1.copy()
498 голосов
/ 18 марта 2010

Когда вы присваиваете dict2 = dict1, вы не делаете копию dict1, это приводит к тому, что dict2 является просто другим именем для dict1.

Чтобы скопировать изменяемые типы, такие как словари,используйте copy / deepcopy модуля copy.

import copy

dict2 = copy.deepcopy(dict1)
130 голосов
/ 12 марта 2014
>>> x={'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> u=x.copy()
>>> v=dict(x)
>>> import copy
>>> w=copy.deepcopy(x)
>>> x['a']=10
>>> x
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> x['b']['m']=40
>>> x
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> u
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> v
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> w
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
59 голосов
/ 12 сентября 2017

В python 3.5+ существует более простой способ получить мелкую копию с помощью оператора ** распаковки **. Определено Пеп 448 .

>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}

** распаковывает словарь в новый словарь, который затем назначается dict2.

Мы также можем подтвердить, что каждый словарь имеет отдельный идентификатор.

>>>id(dict1)
 178192816

>>>id(dict2)
 178192600

Если необходима глубокая копия, то copy.deepcopy () все еще остается в силе.

39 голосов
/ 21 мая 2018

Лучший и самый простой способ создать копию dict в обоих Python 2.7 и 3 - это ...

Чтобы создать копию простого (одноуровневого) словаря:

1. Использование метода dict () вместо создания ссылки, указывающей на существующий dict.

my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1)  # {'message':'Hello Python'}

my_dict2 = dict(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

2. Использование встроенного update () словаря python.

my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2)  # {'message':'Hello Python'}

# Made changes in my_dict1 
my_dict1["name"] = "Emrit"
print(my_dict1)  # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2)  # {'message':'Hello Python'}

Чтобы создать копию вложенного или сложного словаря:

Используйте встроенный модуль copy , который обеспечивает общие операции мелкого и глубокого копирования. Этот модуль присутствует в Python 2.7 и 3. *

import copy

my_dict2 = copy.deepcopy(my_dict1)
35 голосов
/ 06 марта 2014

Вы также можете просто создать новый словарь с пониманием словаря. Это позволяет избежать импорта копии.

dout = dict((k,v) for k,v in mydict.items())

Конечно, в python> = 2.7 вы можете сделать:

dout = {k:v for k,v in mydict.items()}

Но для обратного сжатия лучше использовать метод top.

17 голосов
/ 10 декабря 2016

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

Итак, dict2 = dict1, это приводит к другому связыванию между dict2 и объектом, на который ссылается dict1.

если вы хотите скопировать диктовку, вы можете использовать copy module. Модуль копирования имеет два интерфейса:

copy.copy(x)
Return a shallow copy of x.

copy.deepcopy(x)
Return a deep copy of x.

Различие между мелким и глубоким копированием относится только к составным объектам (объектам, которые содержат другие объекты, например списки или экземпляры классов):

A мелкая копия создает новый составной объект, а затем (по мере возможности) вставляет в него ссылки на объекты, найденные в оригинале.

A глубокая копия создает новый составной объект, а затем рекурсивно вставляет в него копии объектов, найденных в оригинале.

Например, в Python 2.7.9:

>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')

и результат:

>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]
15 голосов
/ 21 ноября 2018

В дополнение к другим предоставленным решениям вы можете использовать ** для интеграции словаря в пустой словарь, например,

shallow_copy_of_other_dict = {**other_dict}.

Теперь у вас будет "мелкая" копия other_dict.

Применительно к вашему примеру:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>

Указатель: разница между мелкими и глубокими копиями

10 голосов
/ 25 октября 2016

Вы можете копировать и редактировать вновь созданную копию за один раз, вызывая конструктор dict с дополнительными аргументами ключевого слова:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
9 голосов
/ 18 марта 2010

Поначалу меня это тоже смутило, потому что я происходил из фона С.

В C переменная - это ячейка памяти с определенным типом. Присвоение переменной копирует данные в ячейку памяти переменной.

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

...