Как сделать полностью неразделенную копию сложного списка? (Глубокая копия не достаточно)
10350 просмотра
5 ответа
Посмотрите на этот код Python:
a = [1, 2, 3]
b = [4, 5, 6]
c = [[a, b], [b, a]] # [[[1, 2, 3], [4, 5, 6]], [[4, 5, 6], [1, 2, 3]]]
c[0][0].append(99) # [[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3, 99]]]
Обратите внимание, как модификация одного элемента c
модифицирует это везде. То есть, если 99
добавлено c[0][0]
, оно также добавлено c[1][1]
. Я предполагаю, что это потому, что Python ловко ссылается на один и тот же объект для c[0][0]
и c[1][1]
. (То есть их id () одинаков.)
Вопрос: Есть ли что-то, что можно сделать, чтобы c
его элементы списка можно было безопасно локально изменить? Выше приведен только пример, моя настоящая проблема имеет список гораздо более сложный, но с аналогичной проблемой.
(Извините за плохо сформулированный вопрос выше. Гуру Python, пожалуйста, не стесняйтесь изменять вопрос или теги, чтобы лучше выразить этот запрос.)
Автор: Ashwin Nanjappa Источник Размещён: 13.11.2019 11:44Ответы (5)
8 плюса
Чтобы преобразовать существующий список списков в тот, где ничего не передано, вы можете рекурсивно скопировать список.
deepcopy
этого будет недостаточно, поскольку он будет копировать структуру как есть, сохраняя внутренние ссылки в качестве ссылок, а не копий.
def unshared_copy(inList):
if isinstance(inList, list):
return list( map(unshared_copy, inList) )
return inList
alist = unshared_copy(your_function_returning_lists())
Обратите внимание, что предполагается, что данные возвращаются в виде списка списков (произвольно вложенных). Если контейнеры относятся к разным типам (например, массивы numpy, dict или пользовательские классы), вам может потребоваться изменить это.
Автор: Brian Размещён: 21.10.2009 03:498 плюса
Когда вам нужна копия, вы явно делаете копию - загадочная [:]
форма «нарезать все» идиоматична, но мой фаворит - гораздо более читаемый подход явного вызова list
.
Если c
он построен неправильно (со ссылками вместо мелких копий на списки, которые вы хотите иметь возможность изменять независимо), лучше всего было бы исправить способ, которым он построен (зачем создавать его неправильно, а затем пытаться исправить это ?!) , но если это не под вашим контролем, можно отменить повреждение - просто включите c
(рекурсивно, если необходимо) с индексом, переназначая соответствующие списки для их копий. Например, если вы точно знаете, что c
структура двухуровневая, как вы указали, вы можете сохранить себя без рекурсии:
def fixthewronglymadelist(c):
for topsublist in c:
for i, L in enumerate(topsublist):
topsublist[i] = list(L)
Несмотря на то, что предлагают другие ответы, copy.deepcopy
было бы трудно склониться к этой особой цели, если бы все, что вам дали, было сделано неправильно c
: выполнение просто copy.deepcopy(c)
аккуратно скопировало бы любую топологию c, включая множественные ссылки на одни и те же подсписки! :-)
5 плюса
В зависимости от вашей ситуации, вы можете работать с глубокой копией этого списка.
Автор: Pesto Размещён: 21.10.2009 02:425 плюса
Используйте [:]
:
>>> a = [1, 2]
>>> b = a[:]
>>> b.append(9)
>>> a
[1, 2]
Альтернативно, используйте copy
илиdeepcopy
:
>>> import copy
>>> a = [1, 2]
>>> b = copy.copy(a)
>>> b.append(9)
>>> a
[1, 2]
copy
работает с объектами, отличными от списков. Для списков это имеет тот же эффект, что и a[:]
. deepcopy
пытается рекурсивно копировать вложенные элементы, и, таким образом, это более «тщательная» операция, чем copy
.
1 плюс
Чтобы увидеть предложение Стефана на работе, сравните два результата ниже:
a = [1, 2, 3]
b = [4, 5, 6]
c = [[a, b], [b, a]]
c[0][0].append(99)
print c
print "-------------------"
a = [1, 2, 3]
b = [4, 5, 6]
c = [[a[:], b[:]], [b[:], a[:]]]
c[0][0].append(99)
print c
Вывод следующий:
[[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3, 99]]]
-------------------
[[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3]]]
Автор: Michael Dillon
Размещён: 21.10.2009 02:47
Вопросы из категории :
- python Обработка XML в Python
- python Как я могу использовать Python itertools.groupby ()?
- python Python: На какой ОС я работаю?
- python Как я могу создать непосредственно исполняемое кроссплатформенное приложение с графическим интерфейсом на Python?
- python Вызов функции модуля с использованием его имени (строки)
- python Звук Питона («Колокол»)
- list Функция транспонирования / распаковки (обратная сторона zip)?
- list How would you make a comma-separated string from a list of strings?
- list Удалить дубликаты из списка <T> в C #
- list Console.WriteLine и общий список
- list Как проверить, если список пуст?
- list Являются ли кортежи более эффективными, чем списки в Python?
- copy Скопируйте все содержимое каталога в C #
- copy Стандартный краткий способ скопировать файл в Java?
- copy Как мне скопировать файл в Python?
- copy В чем разница между глубокой и мелкой копиями?
- copy Могу ли я показать прогресс копирования файла с помощью FileInfo.CopyTo () в .NET?
- copy Как сказать «нет» всем запросам «Вы хотите перезаписать» в копии командного файла?