Share This
Связаться со мной
Крути в низ
Categories
//Копирование объектов в Python

Копирование объектов в Python

17.10.2020Category : Python

Следует сразу сказать, что оператор присваивания = не создаёт копию объекта. Присваивание создаёт новую переменную, которая дублирует ссылку на исходный объект.

Для примера давайте создадим из старого списка новый список (путем присваивания).

old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 'a']] new_list = old_list   new_list[2][2] = 9   print('Old List:', old_list) print('ID of Old List:', id(old_list))   print('New List:', new_list) print('ID of New List:', id(new_list))

Вывод будет следующим:

Old List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ID of Old List: 140673303268168 New List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ID of New List: 140673303268168

Мы видим, что у обеих переменных — old_list и new_list — один id (140673303268168). Если внести изменения в любой из этих список, изменятся оба. Но иногда нам нужно создать копию самого объекта, а не копию ссылки на него.

Для копирования объектов в Python используется модуль copy и следующие методы:

  • copy(). Копирует объект и возвращает поверхностную копию передаваемого аргумента.
  • deepcopy(). Тоже копирует объект, но возвращает полную копию передаваемого аргумента.

Чем отличаются глубокое и поверхностное копирование?

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

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

Пример поверхностного копирования:

import copy  old_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] new_list = copy.copy(old_list)  print("Old list:", old_list) print("New list:", new_list)

Результат:

Old list: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] New list: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Старый список и новый список — разные объекты. Чтобы это доказать, давайте изменим старый список:

import copy  old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]] new_list = copy.copy(old_list)  old_list.append([4, 4, 4])  print("Old list:", old_list) print("New list:", new_list)

Результат:

Old list: [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]] New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]

В этом примере мы создали поверхностную копию old_list. Новый список (new_list) содержит ссылки на исходные вложенные объекты, хранящиеся в старом списке. Когда мы добавили новый вложенный объект в old_list, это не отразилось на new_list, потому что в последнем не было ссылки на этот новый вложенный объект.

Давайте теперь попробуем изменить один из вложенных объектов, ссылки на которые были скопированы в new_list.

import copy  old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]] new_list = copy.copy(old_list)  old_list[1][1] = 'AA'  print("Old list:", old_list) print("New list:", new_list)

Результат:

Old list: [[1, 1, 1], [2, 'AA', 2], [3, 3, 3]] New list: [[1, 1, 1], [2, 'AA', 2], [3, 3, 3]]

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

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

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

Короче говоря, оба объекта становятся полностью независимы друг от друга. Это похоже на концепцию передачи по значению в таких языках, как C ++, Java и C #.

Рассмотрим пример.

import copy  old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]] new_list = copy.deepcopy(old_list)  print("Old list:", old_list) print("New list:", new_list)

Результат:

Old list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]] New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]

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

import copy  old_list = [[1, 1, 1], [2, 2, 2], [3, 3, 3]] new_list = copy.deepcopy(old_list)  old_list[1][0] = 'BB'  print("Old list:", old_list) print("New list:", new_list)

Результат показывает, что изменения отразились только на старом списке:

Old list: [[1, 1, 1], ['BB', 2, 2], [3, 3, 3]] New list: [[1, 1, 1], [2, 2, 2], [3, 3, 3]]

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

В посте использовались материалы статьи «Глубокое и поверхностное копирование в Python» и код из статьи «Python Shallow Copy and Deep Copy».

    Проходите тест по Python и поймите, готовы ли вы идти на курсы
  • 15 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close