Создать копию объекта python

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

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

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

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

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

Давайте разберемся в следующем примере.

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

В приведенном выше выводе мы видим, что обе переменные list1 и list2 имеют один и тот же идентификатор 1909447368968.

Если мы внесем какие-либо изменения в любое значение в list1 или list2, эти изменения отразятся на обоих.

Типы копий в Python

Основной мотив – создать копию объекта Python, которую мы можем изменить, не изменяя исходные данные. В Python есть два метода создания копий.

Мы будем использовать модуль копирования для создания вышеуказанных копий.

Модуль копирования

Модуль copy используется для создания мелкой и глубокой копии. Давайте посмотрим на каждый из его методов.

Мелкая копия

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

Делает копии ссылки на вложенные объекты и не создает копии вложенных объектов. Поэтому, если мы внесем какие-либо изменения в копию объекта, это отразится на исходном объекте. Мы будем использовать функцию copy() для его реализации.

# importing "copy" for copy operations import copy # initializing list 1 list1 = [1, 7, [3,5], 8] # using copy to shallow copy list2 = copy.copy(list1) # original elements of list print("The original elements before shallow copying") for i in range(0,len(list1)): print(list1[i],end=" ") print("\r") # adding and element to new list list2[2][0] = 10 # checking if change is reflected print("The original elements after shallow copying") for i in range(0,len( list1)): print(list1[i],end=" ")
The original elements before shallow copying 1 7 [3, 5] 8 The original elements after shallow copying 1 7 [10, 5] 8

В приведенном выше коде мы сделали изменение в list1, который отражен в другом списке.

import copy list1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] list2 = copy.copy(list1) list1.append([13, 14,15]) print("Old list:", list1) print("New list:", list2)
Old list: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]] New list: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

В приведенном выше коде мы создали неглубокую копию list1. Вновь созданный список 2 содержит ссылку на исходный вложенный объект, хранящийся в списке 1. Затем мы добавили [13, 14, 15] в старый список и подсписок, не скопированный в новый список.

Читайте также:  Форма обратной связи

Глубокая копия на Python

Глубокая копия – это процесс, в котором мы создаем новый объект и рекурсивно добавляем элементы копии. Мы будем использовать метод deecopy(), который присутствует в модуле копирования. Независимая копия создается из исходного цельного объекта. Давайте разберемся в следующем примере.

import copy x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] z = copy.deepcopy(xs) print(x) prin(z)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

В приведенном выше выводе мы видим, что z является клоном x, который мы создали с помощью метода deecopy(). Если мы внесем изменения в один из дочерних объектов, это не повлияет на исходный объект.

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

import copy x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] z = copy.deepcopy(x) x[2][2] = 'Hello' print(x)
import copy list1 = [0, [1, 2], [3,5], 4] # using deepcopy to deep copy list2 = copy.deepcopy(list1) # original elements of list print("The original list: ") for i in range(0,len(list1)): print(list1[i],end=" ") print("\r") # adding and element to new list list2[1][0] = 8 # Change is reflected in l2 print("The new list after deep copying: ") for i in range(0,len( list1)): print(list2[i],end=" ") print("\r") # Change is NOT reflected in original list # as it is a deep copy print("The original elements:") for i in range(0,len( list1)): print(list1[i],end=" ")
The original list: 0 [1, 2] [3, 5] 4 The new list after deep copying: 0 [8, 2] [3, 5] 4 The original elements: 0 [1, 2] [3, 5] 4

Копирование произвольных объектов Python

Мы также можем скопировать произвольные объекты Python, включая пользовательские классы, с помощью метода копирования. Методы copy.copy() и copy.deepcopy() могут использоваться для дублирования любых объектов.

Читайте также:  Javascript innerhtml of table

Давайте разберемся в следующем примере.

import copy class Func_New: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return 'Func_new(%r, %r)' %(self.x, self.y) a = Func_New(50, 56) b = copy.copy(a) print(a) print(b) print(a is b) print(b is a)
Func_new(50, 56) Func_new(50, 56) False False

В приведенном выше коде мы создали класс определения пользователя с именем Func_new и определили __repr __() для проверки объектов. Затем мы создали мелкую копию с помощью модуля копирования. Мы создали экземпляр класса и сверили оригинал и его неглубокую копию.

Что следует помнить

Составные объекты – главное отличие мелкой копии от глубокой. Объекты, которые содержат другие объекты, такие как список или экземпляр класса, называются экземплярами списка или класса. Мы можем копировать произвольные объекты(включая пользовательские классы) с помощью модуля копирования.

Источник

Копирование объектов в 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, потому что в последнем не было ссылки на этот новый вложенный объект.

Читайте также:  Php array to mysql field

Давайте теперь попробуем изменить один из вложенных объектов, ссылки на которые были скопированы в 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».

Источник

Оцените статью