Иногда вам понадобится полная копия объекта, а иногда — использование ссылок. Посмотрите различия в действии.
Python предлагает несколько эффективных подходов к управлению данными. Понимание концепций поверхностного и глубокого копирования имеет решающее значение при работе со структурами данных, такими как вложенные списки, словари или пользовательские объекты.
И поверхностное, и глубокое копирование позволяют создавать копии структур данных, но в отношении вложенных данных они действуют по-разному.
Использование поверхностного копирования
Неглубокое копирование работает путем создания копии структуры верхнего уровня исходного объекта. Это означает, что если исходный объект содержит вложенные объекты, копия будет ссылаться на те же вложенные объекты, что и оригинал. Другими словами, создание поверхностной копии объекта дублирует его внешнюю структуру, а не любые вложенные объекты, которые он может содержать.
Чтобы выполнить поверхностное копирование в Python, вы можете использовать модуль копирования копировать() функция или .copy() метод на объекте.
Рассмотрим пример работа со списком или словарем в Python.
import copy
main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)# Modify the nested list
shallow_copy[2][0] = 99
main_list[2][1] = 100
print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")
В приведенном выше коде основной_список Переменная содержит список, содержащий целые числа, и внутренний список (вложенный объект), содержащий буквы. Функция копирования создает копию основной_список который код сохраняет в другой переменной, неглубокая_копия.
Любые изменения, которые вы вносите в неглубокая_копия вложенный список также напрямую повлияет на список основной_список и наоборот. Эти изменения показывают, что вложенный или внутренний список неглубокая_копия это всего лишь отсылка к тому, что основной_список, применяя изменения в основной_список слишком.
При этом любые изменения, внесенные во внешние элементы (целые числа) в любом неглубокая_копия или основной_список повлияет только на этот экземпляр. Эти внешние элементы сами по себе являются независимыми значениями, а не просто ссылками.
import copy
main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)# Modify the outer items
shallow_copy[0] = "M"
main_list[1] = "N"
print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")
Вывод показывает, что оба внешних элемента списка независимы друг от друга:
Та же идея применима и при работе со словарями.
dict1 = {'ten': 10, 'twenty': 20, 'double':{'thirty': 30, 'sixty': 60}}
dict2 = dict1.copy()# Modify inner and outer elements
dict1['double']['thirty'] = 30.00
dict1['ten'] = 10.00
print(f"The main dictionary, {dict1}")
print(f"The shallow copy dictionary, {dict2}")
Изменения, внесенные во вложенный словарь дикт1 влияют на обоих дикт1 и дикт2. При этом изменения во внешних элементах дикт1 влияют только на него.
Использование глубокого копирования
Вместо ссылки на вложенные объекты исходной копии глубокая копия создает совершенно отдельную копию исходного объекта и его вложенных объектов. Изменение глубокой копии не повлияет на исходный объект и наоборот; это действительно отдельные ценности.
Чтобы сделать глубокую копию в Python, используйте команду глубокая копия() функция модуля копирования.
Рассмотрим пример работы со списком.
import copy
main_list = [200, 300, ["I", "J"]]
deep_copy = copy.deepcopy(main_list)# Modify the inner and outer list
deep_copy[2][0] = "K"
main_list[0] = 500
print(f"The main list: {main_list}")
print(f"The deep copy list: {deep_copy}")
Здесь код выполняет глубокую копию основной_список, создавая независимую копию с именем deep_copy.
Когда вы изменяете вложенный список или внешние элементы в deep_copy, ваши изменения не повлияют на исходный список, и наоборот. Это показывает, что вложенный список или внешние элементы не являются общими для двух копий.
Работа с пользовательскими объектами
Вы можете создать собственный объект, определение класса Python и создание экземпляра класса.
Вот пример создания простого объекта из Книга сорт:
classBook:
def__init__(self, title, authors, price):
self.title = title
self.authors = authors
self.price = price
def__str__(self):
returnf"Book(title='{self.title}', author='{self.authors}', \
price='{self.price}')"
Теперь создайте как поверхностную, так и глубокую копию экземпляра этого Книга класс, используя копировать модуль.
import copy
# Create a Book object
book1 = Book("How to MakeUseOf Shallow Copy", \
["Bobby Jack", "Princewill Inyang"], 1000)# Make a shallow copy
book2 = copy.copy(book1)# Modify the original object
book1.authors.append("Yuvraj Chandra")
book1.price = 50
# Check the objects
print(book1)
print(book2)
Как видите, мелкая копия (книга2) — новый объект, но он ссылается на тот же внутренний объект (список авторов), что и исходный объект (книга1). Следовательно, изменение авторов исходного объекта влияет на оба экземпляра (book1 и book2), а изменение внешнего элемента (цена) влияет только на исходный объект (книга1).
С другой стороны, создание глубокой копии создает независимую копию исходного объекта, включая копии всех содержащихся в нем объектов.
# Create a Book object
book1 = Book("Why MakeUseOf Deep Copy?", \
["Bobby Jack", "Yuvraj Chandra"], 5000)# Make a deep copy
book2 = copy.deepcopy(book1)# Modify the original object
book1.authors.append("Princewill Inyang")
book1.price = 60
# Check the objects
print(book1)
print(book2)
В этом случае глубокая копия (книга2) является полностью независимым объектом, и изменение исходного объекта (книга1) не влияет на это.
Использование поверхностного и глубокого копирования
Крайне важно понимать, что такое глубокое и поверхностное копирование, чтобы вы могли выбрать подходящий подход к манипулированию данными. Вот несколько сценариев, в которых применим каждый метод:
- Используйте неглубокую копию, если хотите реплицировать сложный объект без создания новых экземпляров его вложенных объектов. Этот подход более эффективен с точки зрения использования памяти и быстрее, чем глубокое копирование, поскольку не дублирует вложенные объекты.
- Используйте неглубокую копию, чтобы создать снимок состояния объекта, сохраняя при этом общий доступ к некоторым базовым данным между исходным и скопированным объектами.
- Используйте глубокую копию, если хотите изменить копию объекта, не затрагивая оригинал. При этом создаются независимые копии вложенных объектов, гарантируя, что любые изменения копии не будут применены к оригиналу.
- Глубокое копирование имеет решающее значение, когда вам нужны независимые копии вложенных структур данных, главным образом при работе с рекурсивными или сложными иерархиями объектов.
Производительность и соображения
Поскольку поверхностное копирование не создает новые экземпляры вложенных объектов, оно обычно выполняется быстрее и использует меньше памяти, чем глубокое копирование. Однако оригинал и поверхностная копия могут иметь нежелательные побочные эффекты от изменения общих внутренних элементов.
Особенно для больших и глубоко вложенных структур данных, глубокого копирования, рекурсивная процедура, может работать медленнее и использовать больше памяти. Однако он обеспечивает полную независимость между оригиналом и глубоким дубликатом, что делает сложные манипуляции с данными более безопасными.
Лучший вариант копирования ваших данных
Многие языки программирования используют концепцию поверхностного и глубокого копирования. Понимание этого позволяет манипулировать данными без непредвиденных последствий.
Используя методы поверхностного и глубокого копирования, вы можете выбрать лучший подход для безопасного дублирования структур данных. Понимая влияние на ваши данные, вы получите более надежные и предсказуемые результаты от вашего кода.