Может кто-нибудь, пожалуйста, объясните мне это? Это не имеет никакого смысла для меня.
Я копирую словарь в другой и редактирую второй, и оба меняются. Почему это происходит?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
python
python-3.x
dictionary
reference
MadSc13ntist
источник
источник
dict1
иdict2
указать на тот же самый диктат.Ответы:
Python никогда не копирует объекты неявным образом. Когда вы устанавливаете
dict2 = dict1
, вы заставляете их ссылаться на один и тот же точный объект dict, поэтому, когда вы изменяете его, все ссылки на него продолжают ссылаться на объект в его текущем состоянии.Если вы хотите скопировать диктовку (что редко), вы должны сделать это явно с
или
источник
dir(1)
чтобы увидеть это), но они неявно копируются.int
,float
иbool
экземпляры являются реальными объектами Python, и б) объекты этих типов не копируются неявным образом при их передаче, точно не на уровне семантического Python, и даже не как детали реализации в CPython.copy.deepcopy()
а неdict()
илиdict.copy()
. Imran «s краткий ответ на правой стороне здравого смысла, в отличие от этого ответа.Когда вы назначаете
dict2 = dict1
, вы не делаете копиюdict1
, это приводит к тому,dict2
что вы просто получаете другое имяdict1
.Для того, чтобы скопировать изменяемые типы , как словари, использование
copy
/deepcopy
вcopy
модуле.источник
Хотя
dict.copy()
иdict(dict1)
создает копию, они являются только мелкими копиями. Если вы хотите глубокую копию,copy.deepcopy(dict1)
требуется. Пример:Относительно мелких и глубоких копий из документации по модулю Python
copy
:источник
w=copy.deepcopy(x)
это ключевая линия.dict2 = dict1
иdict2 = copy.deepcopy(dict1)
?В python 3.5+ существует более простой способ получить мелкую копию с помощью оператора ** распаковки **. Определено Пепом 448 .
** распаковывает словарь в новый словарь, который затем назначается dict2.
Мы также можем подтвердить, что каждый словарь имеет отдельный идентификатор.
Если необходима глубокая копия, то метод copy.deepcopy () по-прежнему остается верным .
источник
dict2 = {**dict1, 'key3':'value3'}
Самые лучшие и самые легкие способы создать копию в виде Словаря как в Python 2.7 и 3 являются ...
Чтобы создать копию простого (одноуровневого) словаря:
1. Использование метода dict () вместо генерации ссылки, указывающей на существующий dict.
2. Использование встроенного метода update () в словаре Python.
Чтобы создать копию вложенного или сложного словаря:
Используйте встроенный модуль копирования , который обеспечивает общие операции мелкого и глубокого копирования. Этот модуль присутствует в Python 2.7 и 3. *
источник
dict()
создает мелкую копию, а не глубокую копию. Это означает, что если у вас есть вложенный элемент,dict
то внешнийdict
будет копией, а внутренний дикт будет ссылкой на исходный внутренний диктат.Вы также можете просто сделать новый словарь с пониманием словаря. Это позволяет избежать импорта копии.
Конечно, в python> = 2.7 вы можете сделать:
Но для обратного сравнения лучший метод лучше.
источник
d2 = dict.copy(d1)
также не требует импорта.d2 = d1.copy()
dict.items
уже возвращает пару ключ / значение итеративно. Так что вы можете просто использоватьdict(mydict.items())
(вы также можете просто использоватьdict(mydict)
). Может быть полезно иметь понимание, если вы хотите отфильтровать записи.В дополнение к другим предоставленным решениям, вы можете использовать
**
для интеграции словарь в пустой словарь, например,shallow_copy_of_other_dict = {**other_dict}
,Теперь у вас будет «мелкая» копия
other_dict
.Применительно к вашему примеру:
Указатель: разница между мелкими и глубокими копиями
источник
Операторы присваивания в Python не копируют объекты, они создают привязки между целью и объектом.
Таким образом,
dict2 = dict1
это приводит к другому связыванию междуdict2
и объектом, на которыйdict1
ссылаются.если вы хотите скопировать диктовку, вы можете использовать
copy module
. Модуль копирования имеет два интерфейса:Разница между мелким и глубоким копированием относится только к составным объектам (объектам, которые содержат другие объекты, такие как списки или экземпляры классов):
Неполная копия создает новый объект соединения , а затем (по мере возможности) вставляет ссылки в него на объекты найдены в оригинале.
Глубокая копия создает новый объект соединения , а затем, рекурсивно, вставляет копии в него предметов , найденных в оригинале.
Например, в Python 2.7.9:
и результат:
источник
Вы можете копировать и редактировать вновь созданную копию за один раз, вызывая
dict
конструктор с дополнительными ключевыми аргументами:источник
Поначалу меня это тоже смутило, потому что я пришел из C-фона.
В Си переменная - это место в памяти с определенным типом. Присвоение переменной копирует данные в ячейку памяти переменной.
Но в Python переменные действуют больше как указатели на объекты. Таким образом, присвоение одной переменной другой не делает копию, она просто указывает на то, что имя переменной указывает на тот же объект.
источник
Каждая переменная в python (например,
dict1
илиstr
или__builtins__
является указателем на какой-то скрытый платонический «объект» внутри машины).Если вы установите
dict1 = dict2
, вы просто указываетеdict1
на тот же объект (или область памяти, или любую аналогию, которая вам нравится), какdict2
. Теперь объект, на который ссылается,dict1
является тем же объектом, на который ссылаетсяdict2
.Вы можете проверить:
dict1 is dict2
должно бытьTrue
. Кроме того,id(dict1)
должно быть так же, какid(dict2)
.Вы хотите
dict1 = copy(dict2)
илиdict1 = deepcopy(dict2)
.Разница между
copy
аdeepcopy
?deepcopy
удостоверится, что элементыdict2
(вы указали это в списке?) также являются копиями.Я не использую
deepcopy
много - обычно плохая практика писать код, который нуждается в этом (по моему мнению).источник
dict1
является символом, который ссылается на базовый объект словаря. Назначениеdict1
наdict2
просто присваивает ту же ссылку. Изменение значения ключа с помощьюdict2
символа изменяет базовый объект, что также влияетdict1
. Это смущает.Гораздо проще рассуждать об неизменных значениях, чем о ссылках, поэтому по возможности делайте копии:
Это синтаксически так же, как:
источник
dict2 = dict1
не копирует словарь. Он просто дает программисту второй способ (dict2
) ссылаться на тот же словарь.источник
Есть много способов скопировать объект Dict, я просто использую
источник
dict_2 = dict_1.copy()
гораздо эффективнее и логичнее.Как объяснили другие, встроенный
dict
не делает то, что вы хотите. Но в Python2 (и, вероятно, тоже 3) вы можете легко создатьValueDict
класс, который будет копировать,=
чтобы вы могли быть уверены, что оригинал не изменится.Пожалуйста, обратитесь к шаблону модификации lvalue, обсуждаемому здесь: Python 2.7 - чистый синтаксис для модификации lvalue . Ключевое наблюдение состоит в том , что
str
иint
ведет себя как ценности в Python (даже если они на самом деле неизменные объекты под капотом). Пока вы наблюдаете это, пожалуйста, также обратите внимание, что в этом нет ничего особенногоstr
или волшебногоint
.dict
может использоваться во многом таким же образом, и я могу вспомнить много случаев, когдаValueDict
имеет смысл.источник
следующий код, который содержит dicts, который следует синтаксису json более чем в 3 раза быстрее, чем Deepcopy
источник
я столкнулся со странным поведением при попытке глубокого копирования словарного свойства класса без назначения его переменной
new = copy.deepcopy(my_class.a)
не работает, т.е. модифицируетnew
модифицируетmy_class.a
но если вы делаете,
old = my_class.a
а затемnew = copy.deepcopy(old)
он работает отлично, т.е. изменениеnew
не влияетmy_class.a
Я не уверен, почему это происходит, но надеюсь, что это поможет сэкономить несколько часов! :)
источник
my_class.a
?потому что dict2 = dict1, dict2 содержит ссылку на dict1. Оба dict1 и dict2 указывают на одно и то же место в памяти. Это обычный случай при работе с изменяемыми объектами в Python. Когда вы работаете с изменяемыми объектами в Python, вы должны быть осторожны, так как это трудно отладить. Например, следующий пример.
В этом примере предполагается получить все идентификаторы пользователей, включая заблокированные идентификаторы. Это мы получили из переменной ids, но мы также непреднамеренно обновили значение my_users . Когда вы расширили идентификаторы с заблокированными, my_users были обновлены, потому что идентификаторы ссылаются на my_users .
источник
Копирование с использованием цикла for:
источник
deepcopy
, который построен специально для этой цели?Вы можете использовать напрямую:
где объект dict2 является независимой копией dict1, поэтому вы можете изменять dict2, не затрагивая dict1.
Это работает для любого типа объекта.
источник
__repr__
для восстановления посредством eval, и класс объекта не может находиться в текущей вызываемой области. Даже придерживаясь встроенных типов, это не удастся, если один и тот же объект хранится под несколькими ключами, какdict2
тогда было бы два отдельных объекта.dict1
Вместо этого будет содержаться самоссылочный словарь, в котором он содержитсяEllipsis
. Было бы лучше использоватьdict1.copy()