Я учусь поверхностно, а не поверхностно. глубокое копирование списка в Python. Я узнал, что есть два способа создать копии, в которых исходные значения не изменились, и изменить только новые значения, или наоборот. Это поверхностный и глубокий текст.
Помимо Copy.copy() и Copy.deepcopy(), я узнал, что операторы срезов можно использовать для поверхностного и глубокого копирования списка. В официальной документации Python я смог найти информацию о том, что выполнение correct_rgba = rgba[:], correct_rgba создает неполную копию rgba.
Пример 1.
rgba = ["Red", "Green", "Blue", "Alph"]
correct_rgba = rgba[:]
correct_rgba[-1] = "Alpha"
correct_rgba # ["Red", "Green", "Blue", "Alpha"]
rgba # ["Red", "Green", "Blue", "Alph"]
Однако мне не удалось найти информацию, подтверждающую, является ли Assignment to Slices глубокой копией. Вот пример, найденный в той же документации Python.
Пример 2.
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters[2:5] = ['C', 'D', 'E']
letters # ['a', 'b', 'C', 'D', 'E', 'f', 'g']
letters[:] = []
letters # []
Мои вопросы:
(1) Буквы [2:5] глубоко копируют ['C', 'D', 'E']? Буквы [:] глубоко копируют []?
(2) Как проверить, является ли список поверхностной или глубокой копией?
Вы можете использовать списки вместо строк и проверять их идентификаторы, как в этом ответе, чтобы проверить наличие поверхностных и глубоких копий.
Глубокое или поверхностное копирование не имеет значения для неизменяемых типов, таких как строки.
Назначение слайсам не является ни поверхностным, ни глубоким, в этом нет ничего особенного. Присвоение срезов создает неглубокую копию, поскольку вы присваиваете значения (результат оценки среза), а не ссылки... но эти значения сами могут быть ссылками.






Я не знаю точных ответов, но на самом деле важным вопросом является номер 2: «Как мне проверить, является ли список поверхностной или глубокой копией?»
Ключевое слово is проверяет идентичность (отличную от равенства). Выражение a is b оценивается как True, если переменные a и b ссылаются на один и тот же объект. Чтобы узнать, является ли список l2 глубокой или поверхностной копией списка l1, выполните is сравнение между элементами.
l1 = [MyObject()]
l2 = l1[:]
print(l1[0] is l2[0])
Я бы предостерег вас от использования примитивных типов данных в списке, поскольку они подлежат непредсказуемой оптимизации. Например, в последний раз, когда я проверял, две целочисленные переменные от 0 до 255 всегда имеют один и тот же идентификатор. Я не знаю, ведут ли строки себя подобным образом.
Строковые литералы, состоящие из символов ASCII, которые допустимы в именах переменных, наряду со всеми односимвольными строками ASCII, являются синглтонами как детали реализации CPython, как и пустая строка.
Произошла путаница в терминах:
>>> x = ['C', 'D', 'E']
>>> y=['a', 'b','c','d','e']
>>> y[2:5]=x
>>> y
['a', 'b', 'C', 'D', 'E']
>>> x[0]='XX'
>>> y
['a', 'b', 'C', 'D', 'E']
>>> x
['XX', 'D', 'E']
>>> z=[[1,3],4]
>>> y[0:2]=z
>>> y
[[1, 3], 4, 'C', 'D', 'E']
>>> z[0][0]='XX'
>>> z[1]='OO'
>>> z
[['XX', 3], 'OO']
>>> y
[['XX', 3], 4, 'C', 'D', 'E']
Не уверен, что вы подразумеваете под «всегда копируются». Даже примитивные типы используют ссылки.
@MarkRansom Вы правы, удалили эту часть. Mutable — это действительно то, что я хотел.
@kabanus, я получил ['a', 'b', 'A', 'B', 'C'] печатание y в вашем первом примере, и это затронуло следующий код.
@LEDFantom К сожалению, первая строка неверна. Единственное, что я не скопировал... Исправлено. Я думаю, что точка зрения остается в силе.
Давайте разберем ваши вопросы и опасения:
(1) Есть ли letters[2:5] глубокое копирование ['C', 'D', 'E']? Есть ли letters[:] глубокое копирование []?
Нет, ни одна из этих операций не выполняет глубокое копирование.
letters[2:5] = ['C', 'D', 'E'] — присвоение фрагменту исходного списка. Он заменяет элементы с индексами 2, 3 и 4 новыми значениями, но не создает новую копию списка. Исходный список изменяется на месте.letters[:] = [] также является присвоением срезу, но на этот раз он заменяет весь список пустым списком. Опять же, это изменяет исходный список, а не создает новую копию.(2) Как проверить, является ли список поверхностной или глубокой копией?
Чтобы определить, является ли список поверхностной или глубокой копией, вы можете использовать следующие методы:
Мелкая копия:
id(), чтобы проверить, имеют ли исходный список и скопированный список одинаковый адрес памяти. Если да, то это поверхностная копия.Пример:
original_list = [[1, 2], [3, 4]]
shallow_copy = original_list[:]
print(id(original_list) == id(shallow_copy)) # True
original_list[0][0] = 10
print(shallow_copy) # [[10, 2], [3, 4]] (affected by original list)
Глубокая копия:
id(), чтобы проверить, имеют ли исходный список и скопированный список разные адреса памяти. Если да, то это может быть глубокая копия.Пример:
import copy
original_list = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original_list)
print(id(original_list) != id(deep_copy)) # True
original_list[0][0] = 10
print(deep_copy) # [[1, 2], [3, 4]] (not affected by original list)
Имейте в виду, что эти методы не являются надежными, и могут быть крайние случаи, когда они не могут точно определить, является ли копия поверхностной или глубокой. Однако в большинстве случаев они должны дать вам хорошее представление.
Отвечает ли это на ваш вопрос? В чем разница между поверхностным копированием, глубоким копированием и обычной операцией присваивания?