Найти в Дзене
programmer's notes (python and more)

Программирование на языке Python. Модуль copy - глубокое копирование коллекций

Оглавление

Доброго времени суток, читатели, зрители моего канала programmer's notes. Не забывайте подписываться и писать свои комментарии к моим статьям и видео.

Вложенные коллекции и их копирование с помощью модуля copy

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

Вспоминая азы Python

Начну с известных для вас вещей

ls = [1, 3, 5, 8]
lss = ls

Что означает этот фрагмент? Теперь и ls и lss указывают на один и тот же объект [1, 3, 5, 8]. lss не новый список (объект), а указатель на уже существующий. Помните это, иначе ошибок вам не избежать.

Для копирования списка будет правильно написать

lss = ls[:]

Теперь мы получаем два разных списка ls и lss.

Есть также метод copy(), о котором мы говорили здесь.

И вот тут есть один важный момент. Что если элементами списка (или другой коллекции) являются сложные объекты, т.е. другие коллекции. Рассмотрим пример

#!/usr/bin/python3
ls = [1, [3, 5], 8]
lss = ls[:]
ls[0] = 6
print(ls)
print(lss)
ls[1][0] = 33
print(ls)
print(lss)

Результат выполнения программы

[6, [3, 5], 8]
[1, [3, 5], 8]
[6, [33, 5], 8]
[1, [33, 5], 8]

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

Копирование объектов с помощью модуля copy

Ну а теперь перейдём к новому для нас модулю, который называется copy. Его можно использовать для копирования коллекций. Давайте сразу перейдём к примерам.

Пример 1. Поверхностное копирование, аналогичное lss = ls[:].

#!/usr/bin/python3
import copy
ls = [1, [3, 5], 8]
lss = copy.copy(ls)
ls[0] = 6
print(ls)
print(lss)
ls[1][0] = 33
print(ls)
print(lss)

Результат выполнения программы

[6, [3, 5], 8]
[1, [3, 5], 8]
[6, [33, 5], 8]
[1, [33, 5], 8]

Здесь мы видим знакомую уже нам картину.

Замечание. Только не путайте метод copy() модуля copy и метод copy() объекта список.

Пример 2. Глубокое копирование с помощью метода deepcopy()

#!/usr/bin/python3
import copy
ls = [1, [3, 5], 8]
lss = copy.deepcopy(ls)
ls[0] = 6
print(ls)
print(lss)
ls[1][0] = 33
print(ls)
print(lss)


Результат выполнения программы

[6, [3, 5], 8]
[1, [3, 5], 8]
[6, [33, 5], 8]
[1, [3, 5], 8]

Теперь чётко видно, что список lss стал абсолютно независимом от изначального списка. Метод deepcopy() будет правильно работать, если глубина вложенности будет более двух. Если хотите - проверьте.

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

У вас коллекция марок, а я коплю коллекции
У вас коллекция марок, а я коплю коллекции