Мелкое копирование и глубокое копирование в Python

RedDeveloper
09.03.2023 12:16
Мелкое копирование и глубокое копирование в Python

В python мы можем создать копию объекта с помощью оператора присваивания (=). Но есть проблема в использовании этого оператора для копирования объекта. Если вы внесете изменения в скопированный объект, это также приведет к изменению исходного объекта, с которого мы сделали копию.

Рассмотрим пример копирования объекта с помощью оператора присваивания.

# 'x' is a list of integers
x = [1,2,3,4,5]

# creating a copy of 'x' and assigned to 'y'
y = x

# displaying the contents of 'x' and 'y'
print('list x = ',x)
print('list y = ',y)

# trying to change the first element of 'y'
y[0] = 11

# displaying the contents of 'x' and 'y'
print('\nAfter changing the list y')
print('list x = ',x)
print('list y = ',y)

В приведенном выше сценарии мы создали список под названием 'x' с 5 целыми числами.

Затем создали копию 'x' и присвоили ей значение 'y'.

Мы изменяем первый элемент 'y' на 11. Когда мы изменяем

Список 'y', это также отразится в исходном списке 'x'.

Вывод для приведенного выше сценария

list x =  [1, 2, 3, 4, 5]
list y =  [1, 2, 3, 4, 5]

After changing the list y
list x =  [11, 2, 3, 4, 5]
list y =  [11, 2, 3, 4, 5]

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

Чтобы избежать этой проблемы, мы можем скопировать объект с помощью модуля 'copy'.

Существует два варианта копий, доступных из этого модуля. Это поверхностное копирование с помощью метода copy() и глубокое копирование с помощью метода deepcopy().

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

Неглубокое копирование

import copy

# a list with elements and nested list
x = [1,2,3,[4,5,6]]

# creating a shallow copy of 'x' 
y = copy.copy(x)

# changing the element of list 'y'
y[0]=100

# displaying the contents of 'x' and 'y'
print('\nAfter changing an element in y')
print('list x = ',x)
print('list y = ',y)

# changing the element in the nested list of 'y'
y[3][0]=400

# displaying the contents of 'x' and 'y'
print('\nAfter changing the nested list in y')
print('list x = ',x)
print('list y = ',y)

В приведенном выше сценарии список 'x' содержит 3 целых числа и является вложенным списком (список внутри списка). Затем мы создаем копию 'x' и присваиваем ее 'y'.

После этого мы пытаемся изменить первый элемент(y[0]) на 100 в списке 'y'. Затем мы отображаем содержимое обоих списков 'x' и 'y'. Мы видим, что y[0] меняется на 100, а x[0] не меняется.

До сих пор проблем не было. Здесь проблема возникает, когда мы изменяем вложенный список в 'y'. Здесь мы пытаемся изменить первый элемент(y[3][0]) на 400 из вложенного списка в 'y'. После изменения и отображения содержимого обоих 'x' и 'y', мы можем наблюдать, что изменения, которые мы сделали во вложенном списке 'y', также отражаются в списке 'x'.

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

Вывод для приведенного выше сценария

After changing an element in y
list x =  [1, 2, 3, [4, 5, 6]]
list y =  [100, 2, 3, [4, 5, 6]]

After changing the nested list in y
list x =  [1, 2, 3, [400, 5, 6]]
list y =  [100, 2, 3, [400, 5, 6]]

Глубокое копирование

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

Для демонстрации глубокого копирования мы можем использовать тот же сценарий, что и для поверхностного копирования. Вместо метода copy() мы можем использовать метод deepcopy(), чтобы скопировать список 'x' и присвоить ему значение 'y'.

import copy

# a list with elements and nested list
x = [1,2,3,[4,5,6]]

# creating a deep copy of 'x' 
y = copy.deepcopy(x)

# changing the element of list 'y'
y[0]=100

# displaying the contents of 'x' and 'y'
print('\nAfter changing an element in y')
print('list x = ',x)
print('list y = ',y)

# changing the element in the nested list of 'y'
y[3][0]=400

# displaying the contents of 'x' and 'y'
print('\nAfter changing the nested list in y')
print('list x = ',x)
print('list y = ',y)

Здесь мы пытаемся изменить первый элемент(y[3][0]) на 400 из вложенного списка в 'y'. После изменения и отображения содержимого обоих 'x' и 'y' мы можем наблюдать, что изменения, которые мы сделали во вложенном списке 'y', не изменили вложенный список 'x'.

Вывод для приведенного выше сценария

After changing an element in y
list x =  [1, 2, 3, [4, 5, 6]]
list y =  [100, 2, 3, [4, 5, 6]]

After changing the nested list in y
list x =  [1, 2, 3, [4, 5, 6]]
list y =  [100, 2, 3, [400, 5, 6]]

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?

20.08.2023 18:21

Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией

20.08.2023 17:46

В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox

19.08.2023 18:39

Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest

19.08.2023 17:22

В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!

Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️

18.08.2023 20:33

Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL

14.08.2023 14:49

Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.