Как скопировать список в Python (поверхностное или глубокое копирование)

Узнайте, как скопировать список в Python. Изучите разделение списков, метод copy(), конструкторы списков и усвойте разницу между поверхностными и глубокими копиями.

Попробуйте это решение в редакторе

Обзор

В Python списки — это изменяемые объекты, а переменные содержат в памяти ссылки на эти объекты, а не фактические значения. Это означает, что если вы присвоите список новой переменной (например, `list_b = list_a`), обе переменные ссылаются на один и тот же список. Любая модификация, сделанная через list_b, немедленно повлияет на list_a. Чтобы избежать этого побочного эффекта, необходимо создать явную копию списка.

Python предоставляет несколько способов создания поверхностной копии списка. Неглубокая копия создает новый список, содержащий ссылки на элементы, найденные в исходном списке. Общие методы включают использование встроенного метода списка `.copy()`, использование среза списка `list_a[:]` или передачу списка конструктору `list()`. Все это создает новый контейнер списка, позволяющий независимо добавлять или удалять элементы.

Однако если список содержит вложенные изменяемые объекты (например, списки или словари), неглубокая копия будет дублировать только внешний контейнер; вложенные объекты остаются общими. Изменение вложенного списка в копии приведет к изменению исходного списка. Чтобы предотвратить это, вы должны выполнить глубокое копирование с помощью функции deepcopy() модуля `copy`, которая рекурсивно клонирует каждый объект внутри иерархии.

Код и вывод выполнения

Этот код демонстрирует ловушку присваивания ссылок, поверхностное копирование с использованием list.copy() и глубокое копирование вложенных списков с использованием модуля копирования.

import copy

# 1. The assignment reference trap (Not a copy!)
original = [1, 2, 3]
reference = original
reference.append(99)
print("Reference modification affects original:", original)

# Reset list
original = [1, 2, 3]

# 2. Creating a shallow copy (using list.copy())
shallow_copy = original.copy()
shallow_copy.append(100)
print("\nOriginal:", original)
print("Shallow copy:", shallow_copy)

# 3. The nested list limitation of shallow copies
nested = [[1, 2], [3, 4]]
shallow_nested = nested.copy()
shallow_nested[0].append(99) # Modifying nested list
print("\nOriginal nested:", nested)
print("Shallow nested copy:", shallow_nested)

# 4. Creating a deep copy
nested_original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested_original)
deep_copy[0].append(99)
print("\nOriginal nested:", nested_original)
print("Deep copy (completely independent):", deep_copy)
Терминальный выход
Reference modification affects original: [1, 2, 3, 99]

Original: [1, 2, 3]
Shallow copy: [1, 2, 3, 100]

Original nested: [[1, 2, 99], [3, 4]]
Shallow nested copy: [[1, 2, 99], [3, 4]]

Original nested: [[1, 2], [3, 4]]
Deep copy (completely independent): [[1, 2, 99], [3, 4]]

Пошаговая реализация

  • Используйте my_list.copy() или my_list[:] для создания поверхностной копии структур плоского списка.
  • Избегайте присвоений ссылок, таких как copy_list = my_list, когда вам нужны независимые коллекции.
  • Импортируйте модуль копирования и используйте copy.deepcopy(my_list) для списков, содержащих вложенные изменяемые структуры.
  • Убедитесь, что вы понимаете свои структуры данных, чтобы оптимизировать производительность и объем памяти.

Часто задаваемые вопросы

В чем разница между поверхностной копией и глубокой копией?

Неполная копия копирует самый внешний контейнер, но ссылается на вложенные изменяемые объекты. Глубокая копия рекурсивно дублирует все вложенные контейнеры и объекты, что приводит к полностью изолированным структурам данных.

Нарезка списка (list[:]) быстрее, чем list.copy()?

Они практически идентичны по производительности, поскольку оба выполняют оптимизированные операции C «под капотом». Использование list.copy() обычно предпочтительнее для удобства чтения.

Связанные темы

Рекомендуемые ресурсы Python

Расширьте свои знания с помощью соответствующих интерактивных руководств, шпаргалок и сравнений кода.