Список глубокой копии dicts - PullRequest
1 голос
/ 17 июня 2020

У меня есть список dicts (docs_dicts), и я сделал это:

docs_dicts_dupl = docs_dicts[:]

но когда я внес изменения в docs_dicts_dupl, тогда также изменился docs_dicts.

Однако когда я сделал это:

docs_dicts_dupl = copy.deepcopy(docs_dicts)

, тогда у меня была глубокая копия.

Насколько мне известно, со списками первого было достаточно для глубокой копии - почему это не со списком dicts (изменяемые или неизменяемые элементы?)?

Кроме того, почему со списком dicts copy.deepcopy() по-прежнему работает нормально, а первый вариант - нет?

PS

Небольшой воспроизводимый пример с этим кодом:

import copy

my_list = [{'x':1}, {'y':2}]

my_new_list = my_list[:]
# my_new_list = copy.deepcopy(my_list)

print(my_list)
print(my_new_list)

my_new_list[0]['x'] = 3

print(my_list)
print(my_new_list)

Ответы [ 3 ]

0 голосов
/ 17 июня 2020

но когда я внес изменения в docs_dicts_dupl, тогда также изменились и docs_dicts.

это потому, что list и dict являются изменяемыми структурами данных в python и у них есть copy() метод попробуйте использовать его

a = [1, 2, 3]
b = a.copy()
b.append(4)
print(a)  # [1, 2, 3]
print(b)  # [1, 2, 3, 4]

он работает для dict тоже

0 голосов
/ 17 июня 2020
my_list = [{'x':1}, {'y':2}]
my_new_list = my_list[:] # this is equivalent to copy.copy which does shallow copy

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

In [27]: id(my_new_list[0])
Out[27]: 139671934496112

In [28]: id(my_list[0])
Out[28]: 139671934496112

In [29]: id(my_list)
Out[29]: 139671934847384

In [30]: id(my_new_list)
Out[30]: 139671934597672

# as you can see my_list and my_new_list has different object, 
# cos new object is created but for inside objects references are copied.

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

Я предлагаю вам попробовать тот же фрагмент кода с copy.deepcopy, тогда вы поймете разницу между мелким и глубокая копия.

Проверьте ссылки на объекты для обеих переменных.

my_list = [{'x':1}, {'y':2}]
my_new_list = deepcopy(my_list)
id(my_new_list[0])
id(my_list[0])

Для ref для глубокого и мелкого копирования: https://docs.python.org/3/library/copy.html

0 голосов
/ 17 июня 2020

В первом случае, docs_dicts_dupl = docs_dicts[:] создает новое назначение только для дескриптора списка, ie, id списков будут одинаковыми, и аналогично для членов списка он просто создает ссылки, элементы в списке с одинаковыми позициями будут иметь одинаковые id s, и вам понадобится copy.deepcopy() для назначения новых членов. Этот код может развеять ваши сомнения:

a = [1,2,3]
b = a
print('a = ',a)
print('b = ',b)
b[0] = 6
print('a = ',a)
print('b = ',b)
print('id(a) = ',id(a))
print('id(b) = ',id(b))
print('id(a[0]) = ',id(a[0]))
print('id(b[0]) = ',id(b[0]))
c = copy.deepcopy(a)
print('==========================')
print('After Deep copy :')
print('==========================')
print('id(a) = ',id(a))
print('id(c) = ',id(c))
print('id(a[0]) = ',id(a[0]))
print('id(c[0]) = ',id(c[0]))
print('But when you assign something : id changes for a member of c')
c[0] = 123
print('id(c[0]) = ',id(c[0]))

Вывод:

a = [1,2,3]
b = [1,2,3]
a = [6,2,3]
b = [6,2,3]
id(a) = 140081055605184
id(b) = 140081055605184
id(a[0]) = 9743968
id(b[0]) = 9743968
==========================
After Deep copy :
==========================
id(a) = 140081055605184
id(c) = 140081055605888
id(a[0]) = 9743968
id(c[0]) = 9743968
But when you assign something : id changes for a member of c
id(c[0]) = 140081056537264

Обратите внимание, что строки docs_dicts_dupl = docs_dicts[:] недостаточно для полного копирования списков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...