Копії у Python
Можливо, ви вже знайомі з оператором присвоєння =
: у багатьох мовах програмування ми використовуємо його для створення копії об'єкта того ж типу даних.
Так само ви можете створювати копії у Python, використовуючи =
. Проте цей оператор робить не копію об'єкта, а лише нову змінну із посиланням на один і той же об'єкт.
Розглянемо програму, де створимо список old_list
та передамо посилання на об'єкт оператором =
до new_list
.
Приклад 1: Копіювання з використанням оператора =
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
Як ви бачите, обидві змінні old_list
та new_list
мають однаковий id: 140673303268168
.
Отже, якщо змінити одне зі значень у new_list
чи old_list
, то зміни відбудуться в обох.
По суті, іноді нам потрібно мати оригінальні значення без змін і лише змінювати нові значення, а іноді навпаки. У Python існує два способи створення копій:
- поверхневе копіювання;
- глибоке (повне) копіювання.
Для роботи з ними використовується модуль copy
.
Модуль copy
Цей модуль використовується для операцій глибокого та поверхневого копіювання. Припустимо, вам треба скопіювати складний список, наприклад:
import copy
copy.copy(x)
copy.deepcopy(x)
Тут copy()
поверне поверхневу копію х
. Так само deepcopy()
поверне глибоку копію x
.
Поверхнева копія
Поверхнева копія створює новий об'єкт, який зберігає посилання на оригінальні елементи.
Отже, поверхневе копіювання не створить нових екземплярів вкладених об'єктів, натомість лише скопіює посилання на них. Це означає, що процес копіювання не повторюється.
Приклад 2: Поверхневе копіювання об'єкта
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()
.
Це означає, що буде створений новий та незалежний об'єкт з тим самим контентом. Щоб переконатися у цьому, виведемо обидва у консоль.
Аби перевірити, чи два списки відрізняються, додамо вкладені об'єкти до оригінального.
Приклад 3: Додавання [4,4,4] до old_list
через поверхневе копіювання
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
містить посилання на оригінальний вкладений об'єкт, що зберігається в old_list
. Тоді ми додаємо [4,4,4]
в old_list
. Цей новий список не копіювався у new_list
.
Проте будь-які зміни вкладених об'єктів old_list
показуються в new_list
.
Приклад 4: Додавання нового вкладеного об'єкта за допомогою copy
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
old_list[1][1] = 'AA'
Обидва списки в old_list
та new_list
з індексом [1][1]
були змінені. Це відбувається тому, що обидва списки посилаються на один і той самий об'єкт.
Глибока копія
Глибоке копіювання створює новий об'єкт та рекурсивно додає копії вкладених об'єктів, що є в початкових елементах.
Давайте знову розглянемо приклад 2 — та цього разу скористаємося deepcopy()
для формування глибокої копії. Глибоке копіювання створює незалежну копію оригінального об'єкта та всіх вкладених об'єктів.
Приклад 5: Копіювання за допомогою deepcopy()
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]]
Метод відрізняється від поверхневого копіювання, адже тут зміни, зроблені у вкладених об'єктах old_list
, не вплинуть на new_list
.
Приклад 6: Додавання нового вкладеного об'єкта у список з deepcopy()
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
. Це означає, що обидва списки повністю незалежні — адже old_list
був скопійований рекурсивно.
Ще немає коментарів