В этой статье я расскажу, как скопировать объект с помощью мелкой копии и глубокой копии в Python.
Введение
При программировании нам нужно скопировать существующие данные. Когда мы присваиваем переменную другому оператору, то оператор присваивания не копирует объект, а просто создает новую ссылку на тот же объект.
Давайте приступим к рассмотрению конкретных примеров.
Как использовать функцию copy в Python?
Мелкая копия — это функция, используемая для создания копии существующего объекта коллекции. Когда мы пытаемся скопировать объект коллекции с помощью неглубокой копии, эта функция создает новый объект коллекции и сохраняет ссылки на элементы исходного объекта.
Мы можем использовать неглубокое копирование в Python с помощью модуля копирования. Для выполнения операции неглубокого копирования мы используем метод copy модуля copy.
Метод copy принимает исходный объект коллекции в качестве входных данных и создает новый объект коллекции со ссылкой на элементы исходного объекта коллекции. Затем он возвращает ссылку на новый объект коллекции.
В следующем примере я создам копию данного словаря Python с помощью метода copy:
import copy data = {1: 5, 2: 6, 3: 7, 4: 8} print("Оригинальный словарь:") print(data) new_data = copy.copy(data) print("Новый словарь:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: 8} Новый словарь: {1: 5, 2: 6, 3: 7, 4: 8}
В выходных данных мы видим, что мы создали такой же словарь, как и исходный словарь, приведенный выше.
Как работает неглубокое копирование?
В неглубокой копии, когда создается новый объект, он имеет ссылки на элементы исходного объекта. Если мы попытаемся внести какие-либо изменения во вновь созданный объект, он не будет отражен в исходном объекте, учитывая, что элементы в объектах не должны ссылаться на другой объект, то есть не должно быть никакой вложенности.
Рассмотрим пример:
import copy data = {1: 5, 2: 6, 3: 7, 4: 8} print("Оригинальный словарь:") print(data) new_data = copy.copy(data) print("Новый словарь:") print(new_data) new_data[1] = 99 print("Оригинальный словарь после изменения:") print(data) print("Новый словарь после изменения:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: 8} Новый словарь: {1: 5, 2: 6, 3: 7, 4: 8} Оригинальный словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8} Новый словарь после изменения: {1: 99, 2: 6, 3: 7, 4: 8}
Если мы внесем какие-либо изменения в исходный объект, это также не отразится на копии исходного объекта, учитывая, что вложенность не должна быть выполнена.
Например:
import copy data = {1: 5, 2: 6, 3: 7, 4: 8} print("Оригинальный словарь:") print(data) new_data = copy.copy(data) print("Новый словарь:") print(new_data) data[1] = 99 print("Оригинальный словарь после изменения:") print(data) print("Новый словарь после изменения:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: 8} Новый словарь: {1: 5, 2: 6, 3: 7, 4: 8} Оригинальный словарь после изменения: {1: 99, 2: 6, 3: 7, 4: 8} Новый словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8}
Точно так же, когда мы добавляем какой-либо элемент к исходному объекту, он не будет иметь никакого влияния на новый объект.
Ниже пример:
import copy data = {1: 5, 2: 6, 3: 7, 4: 8} print("Оригинальный словарь:") print(data) new_data = copy.copy(data) print("Новый словарь:") print(new_data) data[7] = 99 print("Оригинальный словарь после изменения:") print(data) print("Новый словарь после изменения:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: 8} Новый словарь: {1: 5, 2: 6, 3: 7, 4: 8} Оригинальный словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8, 7: 99} Новый словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8}
Сценарии, рассмотренные выше, изменяются, когда в объектах присутствует вложенность, то есть когда копируемые объекты содержат другие объекты, изменения, происходящие во вложенных объектах, видны как в исходном, так и в копируемом объекте.
Это можно увидеть в следующем примере:
import copy data = {1: 5, 2: 6, 3: 7, 4: 8, 5: {10: 11}} print("Оригинальный словарь:") print(data) new_data = copy.copy(data) print("Новый словарь:") print(new_data) data[5][10] = 99 print("Оригинальный словарь после изменения:") print(data) print("Новый словарь после изменения:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: 8, 5: {10: 11}} Новый словарь: {1: 5, 2: 6, 3: 7, 4: 8, 5: {10: 11}} Оригинальный словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8, 5: {10: 99}} Новый словарь после изменения: {1: 5, 2: 6, 3: 7, 4: 8, 5: {10: 99}}
При копировании объекта с помощью метода copy.copy создается только копия объекта, передаваемая в качестве параметра методу copy. Элементы внутри объекта не копируются, копируются только ссылки на элементы.
Таким образом, когда в исходном объекте в качестве элементов присутствуют только примитивные типы данных, такие как int, double, string. Изменения не видны новому объекту при выполнении в исходном объекте, поскольку эти типы данных неизменяемы и для каждого изменения создается новый объект.
Но в случае вложенных объектов ссылки не изменяются, и когда мы вносим какие-либо изменения в один из объектов, они видны в другом объекте.
Как использовать deepcopy в Python?
Чтобы избежать проблемы, обсуждаемой при выполнении неглубокого копирования, мы будем использовать метод deepcopy. Метод deepcopy рекурсивно создает копию каждого элемента объекта и не копирует ссылки.
Это можно сделать следующим образом:
import copy data = {1: 5, 2: 6, 3: 7, 4: {10: 11}} print("Оригинальный словарь:") print(data) new_data = copy.deepcopy(data) print("Копия словаря:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: {10: 11}} Копия словаря: {1: 5, 2: 6, 3: 7, 4: {10: 11}}
После использования функции deepcopy изменения, внесенные в исходный объект, не будут отображаться в скопированном объекте, даже если присутствует вложенность.
Пример ниже:
import copy data = {1: 5, 2: 6, 3: 7, 4: {8: 9}} print("Оригинальный словарь:") print(data) new_data = copy.deepcopy(data) print("Копия словаря:") print(new_data) data[4][8] = 99 print("Оригинал после изменения:") print(data) print("Копия после изменения:") print(new_data)
Вывод программы:
Оригинальный словарь: {1: 5, 2: 6, 3: 7, 4: {8: 9}} Копия словаря: {1: 5, 2: 6, 3: 7, 4: {8: 9}} Оригинал после изменения: {1: 5, 2: 6, 3: 7, 4: {8: 99}} Копия после изменения: {1: 5, 2: 6, 3: 7, 4: {8: 9}}
Здесь мы видим, что в отличие от copy, когда мы копируем объект с помощью deepcopy, изменения, внесенные в исходный объект, не влияют на скопированный объект и наоборот, потому что объект, созданный методом deepcopy, не содержит ссылок на элементы исходного словаря, в то время как в случае метода copy вновь созданные объекты содержат ссылки на элементы исходного объекта.
Заключение
В этой статье вы узнали о неглубоком копировании и глубоком копировании в Python.
Вы видели, что при наличии вложенных объектов для создания копии объектов следует использовать функцию deepcopy. Мы также можем написать программы, используемые в этой статье, с обработкой исключений с помощью python try, чтобы сделать программы более надежными или чтобы систематически обрабатывать ошибки.
Здравствуйте, а как будет работать deepcopy в случае циклической вложенности?
mainList[0,1]
mainList.append[mainList]
shadowList = copy.deepcopy
Спасибо, Егор, за такой пошаговый и понятный разбор темы, я только обучаюсь работать в этой сфере, поэтому информация была очень актуальна
пожалуйста))