Делает ли массив nums глубокую копию букв [2:5] = ['C', 'D', 'E']?

Я учусь поверхностно, а не поверхностно. глубокое копирование списка в 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) Как проверить, является ли список поверхностной или глубокой копией?

Вы можете использовать списки вместо строк и проверять их идентификаторы, как в этом ответе, чтобы проверить наличие поверхностных и глубоких копий.

Ignatius Reilly 25.04.2024 17:56

Глубокое или поверхностное копирование не имеет значения для неизменяемых типов, таких как строки.

interjay 25.04.2024 17:59

Назначение слайсам не является ни поверхностным, ни глубоким, в этом нет ничего особенного. Присвоение срезов создает неглубокую копию, поскольку вы присваиваете значения (результат оценки среза), а не ссылки... но эти значения сами могут быть ссылками.

Ignatius Reilly 25.04.2024 18:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
123
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не знаю точных ответов, но на самом деле важным вопросом является номер 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, как и пустая строка.

ShadowRanger 26.04.2024 21:48

Произошла путаница в терминах:

  1. Кажется, вопрос заключается в том, присваивает ли присвоение срезу ссылку на исходный список или нет. Вот один из способов проверить это:
    >>> 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']
  1. Задание выполняет глубокую копию списка или копирует ссылку на исходные элементы. Это нельзя протестировать со списком примитивных типов, которые нельзя изменить без ссылки на другое значение, но нам нужны изменяемые вещи, чтобы их можно было изменить без изменения ссылки:
    >>> 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']

Не уверен, что вы подразумеваете под «всегда копируются». Даже примитивные типы используют ссылки.

Mark Ransom 26.04.2024 15:28

@MarkRansom Вы правы, удалили эту часть. Mutable — это действительно то, что я хотел.

kabanus 26.04.2024 15:33

@kabanus, я получил ['a', 'b', 'A', 'B', 'C'] печатание y в вашем первом примере, и это затронуло следующий код.

LED Fantom 26.04.2024 18:14

@LEDFantom К сожалению, первая строка неверна. Единственное, что я не скопировал... Исправлено. Я думаю, что точка зрения остается в силе.

kabanus 26.04.2024 20:56
Ответ принят как подходящий

Давайте разберем ваши вопросы и опасения:

(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)

Имейте в виду, что эти методы не являются надежными, и могут быть крайние случаи, когда они не могут точно определить, является ли копия поверхностной или глубокой. Однако в большинстве случаев они должны дать вам хорошее представление.

Другие вопросы по теме