Понякога ще искате пълно копие на обект, друг път ще искате той да използва препратки. Вижте разликите в действието.

Python предлага няколко ефективни подхода за управление на данни. Разбирането на концепциите за плитко и дълбоко копиране е от решаващо значение при работа със структури от данни като вложени списъци, речници или персонализирани обекти.

И плиткото, и дълбокото копиране ви позволяват да правите реплики на структури от данни, но те действат по различен начин по отношение на вложените данни.

Използване на плитко копиране

Плиткото копиране работи, като създава копие на структурата от най-високо ниво на оригиналния обект. Това означава, че ако оригиналният обект съдържа вложени обекти, копието ще препраща към същите вложени обекти като оригинала. С други думи, правенето на плитко копие на обект дублира най-външната му структура, а не всички вложени обекти, които може да съдържа.

За да извършите плитко копиране в Python, можете да използвате модула за копиране копие() функция или .копие() метод върху обекта.

instagram viewer

Помислете за пример за работа със списък или речник в 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}")

Промени, направени във вложения речник на dict1 засягат и двете dict1 и dict2. В същото време промените във външните елементи на dict1 засяга само него.

Използване на Deep Copy

Вместо да препраща към вложените обекти на оригиналното копие, дълбокото копие прави напълно отделно копие на оригиналния обект и неговите вложени обекти. Модифицирането на дълбокото копие няма да засегне оригиналния обект и обратното; те са наистина отделни ценности.

За да направите дълбоко копие в Python, използвайте deepcopy() функция на модула за копиране.

Помислете за пример за работа със списък.

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}")

Тук кодът извършва дълбоко копие на основен_списък, създавайки независимо копие с име дълбоко_копиране.

Когато модифицирате вложения списък или външни елементи в дълбоко_копиране, вашите промени не засягат оригиналния списък и обратното. Това показва, че вложеният списък или външните елементи не се споделят между двете копия.

Работа с персонализирани обекти

Можете да създадете персонализиран обект от дефиниране на клас Python и създаване на екземпляр на класа.

Ето пример за създаване на прост обект от a Книга клас:

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) не го засяга.

Използва се за плитко копиране и дълбоко копиране

Жизненоважно е да разберете дълбокото и повърхностното копиране, за да можете да изберете подходящия подход за манипулиране на данни. Ето някои сценарии, при които всеки метод е приложим:

  • Използвайте плитко копие, ако искате да копирате сложен обект, без да генерирате нови екземпляри на неговите вложени обекти. Този подход е по-ефективен за паметта и по-бърз от дълбокото копиране, защото не дублира вложени обекти.
  • Използвайте плитко копие, за да създадете моментна снимка на състоянието на обект, като същевременно споделяте някои основни данни между оригиналния и копирания обект.
  • Използвайте дълбоко копие, ако искате да модифицирате реплика на обект, без да засягате оригинала. Това генерира независими копия на вложени обекти, като гарантира, че промените в копието не се прилагат към оригинала.
  • Дълбокото копиране е критично, когато се нуждаете от независими копия на вложени структури от данни, главно когато работите с рекурсивни или сложни йерархии на обекти.

Изпълнение и съображения

Тъй като плиткото копиране не генерира нови екземпляри на вложени обекти, то обикновено работи по-бързо и използва по-малко памет от дълбокото копие. Въпреки това, оригиналът и плиткото копие може да имат нежелани странични ефекти от промяна на споделени вътрешни елементи.

Особено за големи и дълбоко вложени структури от данни, дълбоко копиране, рекурсивна процедура, може да бъде по-бавно и да използва повече памет. Въпреки това, той гарантира пълна независимост между оригинала и дълбокия дубликат, което прави сложната манипулация на данни по-сигурна.

Най-добрата опция за копиране на вашите данни

Много езици за програмиране използват концепцията за плитко и дълбоко копиране. Разбирането му ви позволява да манипулирате данни без непредвидени последствия.

Като използвате техники за плитко и дълбоко копиране, можете да изберете най-добрия подход за безопасно дублиране на вашите структури от данни. Като разберете ефектите върху вашите данни, ще получите по-надеждни и предвидими резултати от вашия код.