Метод copy() для list: глубокое и поверхностное копирование листов

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

Так вот, есть несколько методов скопировать элементы одного листа в другой, и даже есть метод copy(), который и позволяет нам это сделать:

my_lst = [2, 5, 4, 3, 7] #создадим лист my_lst с элементами
new_lst = my_lst.copy() #скопируем элементы с листа my_lst в 
новый лист new_lst
print(new_lst)#распечатаем элементы нашего нового листа new_lst, 
проверим.

Итак, мы провели копирование элементов с одного листа в другой используя метод copy() для list, и вроде все хорошо и отлично, операция увенчалась успехом! Но, давайте создадим наш исходный список немного по-другому, с вложенным списком:

my_lst = [2, 5, 4, 3, 7, [12, 13, 14]]#Список my_lst с вложенным 
списком внутри

Методом append() мы можем добавлять элементы в список, а если обратимся по индексу к скопированному списку, т.е. к new_lst, при чем так, что бы получить вложенный список, т.е. в моем примере это индекс 5, так как индексация начинается с 0, и вложенный список имеет индекс 5, и добавим элемент в этот вложенный список:

new_lst[5].append(15) #Обратились к исходному списку по индексу, 
который соответвует элементу вложенного списка и добавили в него 15
print(new_lst)# выведем элементы скопированного списка, проверим, 
добавился ли элемент 15

И в результате, мы видим, что он добавился, т.е. вывод будет вот таким:

[2, 5, 4, 3, 7, [12, 13, 14, 15]]

А давайте теперь посмотрим на наш исходный список, не изменился ли он, случайно:

print(my_lst)#вывод в консоль исходного списка

И что мы видим? Он тоже почему-то изменился, хотя мы в него ничего не добавляли и вообще не изменяли его!

Давайте попробуем разобраться, почему же так получилось?

Все просто: элементы в списке хранятся не по значениям, а по ссылкам на эти значения в памяти компьютера, и если первые пять элементов ссылаются на объекты типа int, то шестой элемент ссылается объест типа list, внутри которого тоже есть свои элементы типа int. И, когда мы обращаемся по индексу 5 к этому элементу, мы обращаемся к листу, по ссылке и естественно, мы можем этот лист менять. Метод copy() для list на самом деле копируе только ссылки, а не сами элементы!

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

Это и есть поверхностное копирование списков!

А как же быть, как произвести копирование, что бы потом можно было изменять скопированный список, работать с ним не изменяя исходный?

Все тоже очень просто, в Python для этого есть так называемое глубокое копирование списка, и мы можем его применить! Для этого необходимо использовать стандартный модуль copy и его метод deepcopy().

import copy #импортируем стандартный модуль


my_lst = [2, 5, 4, 3, 7, [12, 13, 14]]# создаем исходный список
new_lst = copy.deepcopy(my_lst)# производим копирование с исходного 
списка в новый, используя модуль copy и его метод deepcopy
print(new_lst)# выводим скопированный список, проверяем, произошло ли 
копирование
new_lst[5].append(15)# добавляем элемент в скопированный список
print(my_lst)# выводим исходный список и видим, что он не изменился
print(new_lst)# выводим новый список и видим, что в него элемент добавился

Итак, мы получили то, что и хотели: наши списки не зависимые друг от друга, это и называется глубоким копированием списков и происходит благодаря реверсивному вхождению метода deepcopy во внутрь вложенного списка и копированию всех его элементов, а метод copy() производит копирование вложенного списка целиком, т.е. просто ссылку на это список.

Рейтинг
( 1 оценка, среднее 5 из 5 )
Понравилась статья? Поделиться с друзьями:
Комментарии: 2
  1. Русский Иван

    :idea:

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: