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

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

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

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

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

Источник

copy — Shallow and deep copy operations¶

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).

Return a shallow copy of x.

Raised for module specific errors.

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Two problems often exist with deep copy operations that don’t exist with shallow copy operations:

  • Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
  • Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.

The deepcopy() function avoids these problems by:

  • keeping a memo dictionary of objects already copied during the current copying pass; and
  • letting user-defined classes override the copying operation or the set of components copied.

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

Shallow copies of dictionaries can be made using dict.copy() , and of lists by assigning a slice of the entire list, for example, copied_list = original_list[:] .

Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. In fact, the copy module uses the registered pickle functions from the copyreg module.

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__() . The former is called to implement the shallow copy operation; no additional arguments are passed. The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the __deepcopy__() implementation needs to make a deep copy of a component, it should call the deepcopy() function with the component as first argument and the memo dictionary as second argument. The memo dictionary should be treated as an opaque object.

Discussion of the special methods used to support object state retrieval and restoration.

Источник

Модуль copy — поверхностное и глубокое копирование объектов

Python 3 логотип

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

copy.copy(x) — возвращает поверхностную копию x.

copy.deepcopy(x) — возвращает полную копию x.

Исключениеcopy.error — возникает, если объект невозможно скопировать.

Разница между поверхностным и глубоким копированием существенна только для составных объектов, содержащих изменяемые объекты (например, список списков, или словарь, в качестве значений которого — списки или словари):

  • Поверхностная копия создает новый составной объект, и затем (по мере возможности) вставляет в него ссылки на объекты, находящиеся в оригинале.
  • Глубокая копия создает новый составной объект, и затем рекурсивно вставляет в него копии объектов, находящихся в оригинале.

Для операции глубокого копирования часто возникают две проблемы, которых нет у операции поверхностного копирования:

  • Рекурсивные объекты (составные объекты, которые явно или неявно содержат ссылки на себя) могут стать причиной рекурсивного цикла;
  • Поскольку глубокая копия копирует всё, она может скопировать слишком много, например, административные структуры данных, которые должны быть разделяемы даже между копиями.

Функция deepcopy решает эти проблемы путем:

  • Хранения «memo» словаря объектов, скопированных во время текущего прохода копирования;
  • Позволения классам, определенным пользователем, переопределять операцию копирования или набор копируемых компонентов.

Этот модуль не копирует типы вроде модулей, классов, функций, методов, следа в стеке, стековых кадров, файлов, сокетов, окон, и подобных типов.

Поверхностная копия изменяемых объектов также может быть создана методом .copy() у списков (начиная с Python 3.3), присваиванием среза (copied_list = original_list[:]), методом .copy() словарей и множеств. Создавать копию неизменяемых объектов (таких, как, например, строк) необязательно (они же неизменяемые).

Для того, чтобы определить собственную реализацию копирования, класс может определить специальные методы __copy__() и __deepcopy__(). Первый вызывается для реализации операции поверхностного копирования; дополнительных аргументов не передается. Второй вызывается для реализации операции глубокого копирования; ему передается один аргумент, словарь memo. Если реализация __deepcopy__() нуждается в создании глубокой копии компонента, то он должен вызвать функцию deepcopy() с компонентом в качестве первого аргумента и словарем memo в качестве второго аргумента.

Для вставки кода на Python в комментарий заключайте его в теги

Источник

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