Эта статья была первоначально разделена на Мой блог Анкет
Сегодня мы будем обсуждать копию на 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”