Рубрики
Без рубрики

Присвоение против неглубокой копии против глубокой копии в Python

Эта статья была первоначально поделилась в моем блоге. Сегодня мы будем обсуждать копию на Python. Th … Tagged с производительностью, новичками, Python, Tuperial.

Эта статья была первоначально разделена на Мой блог Анкет

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

1 – оператор назначения (=) 2 – мелкая копия 3 – глубокая копия

Оператор назначения (=)

>>> a = [1, 2, 3, 4, 5]
>>> b = a

В приведенном выше примере оператора назначения он не делает копию объектов Python, вместо этого он копирует адрес памяти (или указатель) из A к b В (b = a) Анкет Что означает оба A & b указывая на тот же адрес памяти.

Здесь мы можем использовать id () Метод получения адреса объекта в памяти и проверить, указывают ли оба списка одну и ту же память.

>>> id(a) == id(b)
True

>>> print('id of a - {}, id of b - {}'.format(id(a), id(b)))
id of a - 140665942562048, id of b - 140665942562048

Итак, здесь, если вы редактируете новый список, он также будет обновлен в исходном списке также –

>>> b.append(6)
>>> a
[1, 2, 3, 4, 5, 6]
>>> b
[1, 2, 3, 4, 5, 6]

Потому что в памяти есть только один экземпляр этого списка.

Мелкая копия

Неглубокая копия конструирует новый составной объект, а затем (в той степени, возможную) вводит ссылки на его объекты, найденные в оригинале.

У нас есть 3 разных способа создать мелкую копию –

nums = [1, 2, 3, 4, 5]      

>>> import copy

>>> m1 = copy.copy(nums)       # make a shallow copy by using copy module
>>> m2 = list(nums)    # make a shallow copy by using the factory function
>>> m3 = nums[:]       # make a shallow copy by using the slice operator

Здесь все приведенные выше списки содержит те же значения, что и исходный список –

>>> print(nums == m1 == m2 == m3)
True

Но адрес памяти каждого отличается –

>>> print('nums_id - {}, m1_id - {}, m2_id - {}, m3_id = {}'.format(id(nums), id(m1), id(m2), id(m3)))
nums_id - 140665942650624, m1_id - 140665942758976, m2_id - 140665942759056, m3_id = 140665942692000

Это означает, что на этот раз объект каждого списка имеет свой независимый адрес памяти.

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

>>> import copy

>>> a = [[1, 2], [3, 4]]            
>>> b = copy.copy(a)

>>> id(a) == id(b)
False

>>> b[0].append(5)
>>>
>>> b
[[1, 2, 5], [3, 4]]
>>> a
[[1, 2, 5], [3, 4]]      # changes reflected in original list also

Как вы видите в приведенном выше примере, в то время как мы изменяем элементы внутреннего списка в новом списке, он также обновляется в исходном списке, потому что a [0] и b [0] все еще указывают на тот же адрес памяти (исходный список).

>>> print('a[0] - {} , b[0] - {}'.format(id(a[0]), id(b[0])))       
a[0] - 140399422977280 , b[0] - 140399422977280
>>>

>>> id(a[0]) == id(b[0])
True
>>> id(a[1]) == id(b[1])
True

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

Это характеристика мелкой копии.

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

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

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

Чтобы достичь глубокой копии, мы должны импортировать копия модуль. И использовать copy.deepcopy () Анкет

>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6]]  
>>> b = copy.deepcopy(a)                     

>>> id(a) == id(b)
False

>>> id(a[0]) == id(b[0])      # memory address is different      
False

>>> a[0].append(8)            # modify the list                                                                                                                                            


>>> a
[[1, 2, 3, 8], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]        # New list's elements didn't get affected

Как вы видите выше, исходный список не затронут.

Разница между мелким и глубоким копированием имеет отношение только к составным объектам (объектам, которые содержат другие объекты, такие как списки или экземпляры класса).

Надеюсь, вам понравится объяснение оператора назначения, неглубокая копия и глубокая копия. Тем не менее, если какие -либо сомнения или улучшение в отношении копии в Python спросите в разделе комментариев.

Ссылки: https://docs.python.org/2/library/copy.html

Оригинал: “https://dev.to/sharmapacific/assignment-vs-shallow-copy-vs-deep-copy-in-python-5c72”