Python копия объекта класса

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

Читайте также:  Что называют html страницами

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

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

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

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

Читайте также:  При наведении на текст, появляется скрытый текст - BlogGood.ru

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

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

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] в старый список и подсписок, не скопированный в новый список.

Читайте также:  Php вывести все поля таблицы

Глубокая копия на 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() могут использоваться для дублирования любых объектов.

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

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 __() для проверки объектов. Затем мы создали мелкую копию с помощью модуля копирования. Мы создали экземпляр класса и сверили оригинал и его неглубокую копию.

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

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

Источник

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