1031

Поверхностное и глубокое копирование в Python

Копирование в Python

При разработке программного обеспечения программистам часто приходится иметь дело с операцией копирования объектов. Это помогает оптимизировать код, реализовать сложные функции и в целом повышает вычислительную эффективность приложения. Однако, при копировании вложенных списков и словарей программиста может ждать неочевидный сюрприз, когда разные переменные связываются с одними и теми же ячейками памяти. Таким образом, при изменении одной такой переменной, меняются и все остальные, которые были с ней связаны.

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

Поверхностное копирование

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

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

 

Для того, чтобы посмотреть как это работает на практике, создадим массив содержащий вложенный список, а затем сделаем его копию с помощью метода copy:

>>> sublist = []
>>> outer_list = [42, 73, sublist]
>>> copy_list = outer_list.copy()

Теперь убедимся в том, что у нас получились два разных объекта. Для этого:

>>> copy_list is outler_list
False
>>> copy_list[0] = 0
>>> outler_list     # Не повлияло на исходный
[42, 73, []]

Как видим, сейчас все работает предсказуемо, и даже внесение корректировок в copy_list никак не отражается на outer_list. Однако, если мы захотим отредактировать вложенный список sublist — изменения коснутся и оригинального и скопированного объекта:

>>> sublist.append (999)
>>> copy_list
[0, 73,  [999]]
>>> outer_list
[42, 73,  [999]]

Такое копирование в языке программирования Python называется поверхностным.

Если рассмотреть ситуацию глубже, то на самом деле модификация sublist не затрагивает содержимое самих объектов copy_list и outer_list. Просто этот элемент относится к другой ячейке памяти, которую можно изменять независимо от них. 

 

Глубокое копирование

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

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

 

Чтобы посмотреть как это работает на практике, создадим список с двумя уровнями вложенности:

>>> a = [1, [2, [3, 4], 5], 6]
>>> a
[1, [2, [3, 4], 5], 6]

Далее, чтобы выполнить глубокое копирование импортируем модуль copy. Для этого в коде пишем такую строку:

>>> import copy

Теперь можем выполнить непосредственно копирование:

>>> b = copy.deepcopy (a)

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

>>> a[0] = 111
>>> a[1][0] = 222
>>> a[1][1][0] = 333
>>>
>>> a
[111, [222, [333, 4], 5], 6]
>>>
>>>
>>> b
[1, [2, [3, 4], 5], 6]

Где изучать язык Python

Python — это один из наиболее востребованных и широко используемых языков программирования, поддерживаемый Google. Если вы хотите освоить профессию Python-разработчика, присоединяйтесь к бесплатным курсам в лаборатории SpaceLAB. У нас вы сможете пройти обучение на реальных проектах, под кураторством опытных менторов. Наиболее успешные студенты получат возможность трудоустройства в AVADA MEDIA — одну из лучших IT-компаний Украины.