Way23
Главная
По категориям
Контакты
Главная
По категориям
Контакты

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

Перевод статьи Python Shallow Copy and Deep Copy.

Копирование объектов в 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

Обе переменные ссылаются на один объект, это подтверждает одинаковый идентификатор объекта 140673303268168. Так что при изменении значений в переменных new_list и old_list, изменение будет видно в обоих переменных.

Иногда нужно оставить исходное значение без изменений и модифицировать только новое. В Python, есть два способа сделать копию: поверхностное копирование и глубокое копирование.

Модуль Copy

Модуль copy используется для поверхностного и глубокого копирования. Например:

import copy

copy.copy(x)
copy.deepcopy(x)

Метод copy() возвращает поверхностную копию x, а метод deepcopy() возвращает глубокую копию x.

Поверхностное копирование

Поверхностное копирование создаёт новый объект и копирует ссылки на все вложенные объекты. Это означает что процесс копирования не рекурсивный и не создаёт копий вложенных объектов.

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]]

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

Чтобы проверить что объекты разные добавим в один из списков новый элемент:

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).

Попробуем изменить один из вложенных объектов:

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]]

Мы изменили вложенный в в оригинальный объект список (old_list[1]). Так как ссылки на вложенные элементы в двух списках одинаковые, изменение вложенного списка отразилось и на old_list и на new_list.

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

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

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]]

В этом примере не видно отличий от использования функции copy(). Изменения видны если модифицировать вложенный список:

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]]

Изменения видны только в списке old_list, так как список new_list содержит копии всех вложенных объектов.

Последниее изменение: 24.08.2023, 06:42