Яка різниця між дрібною копією, глибокою копією та звичайною операцією призначення?


210
import copy

a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}

a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)


print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))

Я отримую такі результати:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Якщо я виконую глибоку копію:

a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)

результати однакові:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

Якщо я працюю над операціями по призначенню:

a1 = a
b1 = b
c1 = c
d1 = d

то результати такі:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True

Чи може хтось пояснити, що саме має значення між копіями? Це щось, що стосується змінних та незмінних об'єктів? Якщо так, чи можете ви мені поясніть, будь ласка?

Відповіді:


364

Нормальні операції з присвоєння просто вказують нову змінну на існуючий об'єкт. У Документах пояснити різницю між дрібної і глибокої копії:

Різниця між дрібним і глибоким копіюванням стосується лише складних об'єктів (об'єктів, що містять інші об'єкти, наприклад, списки або екземпляри класу):

  • Неглибока копія конструює новий складений об'єкт і потім (наскільки це можливо) вставляє в нього посилання на об'єкти, знайдені в оригіналі.

  • Глибока копія конструює новий складний об'єкт, а потім, рекурсивно, вставляє в нього копії об'єктів, знайдених в оригіналі.

Ось невеличка демонстрація:

import copy

a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]

Використовуючи для копіювання звичайні операції призначення:

d = c

print id(c) == id(d)          # True - d is the same object as c
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Використання дрібної копії:

d = copy.copy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

Використання глибокої копії:

d = copy.deepcopy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # False - d[0] is now a new object

5
це допущення те саме, що неглибока копія?
дешанк

35
@Dshank No. Неглибока копія створює новий об'єкт, тоді як призначення просто вказує нову змінну на існуючий об'єкт. Будь-які зміни існуючого об'єкта вплинуть на обидві змінні (із призначенням).
grc

13
@grc "Будь-які зміни в існуючому об'єкті вплинуть на обидві змінні (із призначенням)" - це твердження справедливо лише для об'єктів, що змінюються, а не змінних типів, таких як string, float, кортежі.
Неєрав

1
@grc Але я спробував приклад (я видалити новий рядок тут.) list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)На newlistдисплеї ще [[1, 2], [3, 4]]. Але list_[0]це список, який можна змінити.
Елстон

1
@Stallman list_[0]є мутаційним , але ви не мутуєте / не змінюєте його. Спробуйте list_[0].append(9)або list_[0][0] = 7замість цього.
grc

46

Для незмінних об'єктів немає необхідності в їх копіюванні, оскільки дані ніколи не зміняться, тому Python використовує ті самі дані; ідентифікатори завжди однакові. Для об'єктів, що змінюються, оскільки вони можуть потенційно змінюватися, [неглибока] копія створює новий об’єкт.

Глибока копія пов'язана з вкладеними структурами. Якщо у вас є список списків, то також глибоко скопіюйте copiesвкладені списки, тож це рекурсивна копія. За допомогою лише копії у вас є новий зовнішній список, але внутрішні списки - це посилання.

Призначення не копіюється. Він просто встановлює посилання на старі дані. Тому вам потрібна копія, щоб створити новий список з тим самим вмістом.


With just copy, you have a new outer list but inner lists are references.Що стосується внутрішніх списків, чи буде скопійований вплив на оригінальний? Я створюю список подібних списків list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]і newlistзалишається тим самим, тому внутрішній список є посиланнями?
Елстон

1
@Stallman ви не змінюєте тут посилання, просто створивши новий список і призначивши його як перший елемент однієї з копій. спробуй зробитиlist_[0][0] = 7
перреальне

20

Для незмінних об'єктів створення копії не має особливого сенсу, оскільки вони не збираються змінюватися. Для змінюваних об'єктів assignment, copyіdeepcopy веде себе по- різному. Давайте поговоримо про кожен з них на прикладах.

Операція присвоєння просто призначає посилання джерела на місце призначення, наприклад:

>>> i = [1,2,3]
>>> j=i
>>> hex(id(i)), hex(id(j))
>>> ('0x10296f908', '0x10296f908') #Both addresses are identical

Зараз iі jтехнічно посилається на той самий список. Обидва iі jмають однакову адресу пам'яті. Будь-яке оновлення до будь-якого з них буде відображено для іншого. наприклад:

>>> i.append(4)
>>> j
>>> [1,2,3,4] #Destination is updated

>>> j.append(5)
>>> i
>>> [1,2,3,4,5] #Source is updated

З іншого боку , copyі deepcopyстворює нову копію змінної. Тож тепер зміни оригінальної змінної не відображатимуться на змінній копії та навпаки. Однакcopy(shallow copy) не створює копію вкладених об'єктів, а просто копіює посилання на вкладені об'єкти. Глибока копія рецидивує всі вкладені об'єкти.

Деякі приклади для демонстрації поведінки copyтаdeepcopy :

Приклад плоского списку з використанням copy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Приклад вкладеного списку, використовуючи copy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.copy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x10296f908') #Nested lists have same address

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well

Приклад плоского списку з використанням deepcopy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

Приклад вкладеного списку, використовуючи deepcopy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.deepcopy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable    

18

Давайте подивимось на графічному прикладі, як виконується наступний код:

import copy

class Foo(object):
    def __init__(self):
        pass


a = [Foo(), Foo()]
shallow = copy.copy(a)
deep = copy.deepcopy(a)

введіть тут опис зображення


5

a, b, c, d, a1, b1, c1 і d1 - це посилання на об'єкти в пам'яті, які однозначно ідентифікуються за їх ідентифікаторами.

Операція призначення присвоює посилання на об'єкт у пам'яті та призначає це посилання новому імені. c=[1,2,3,4]це призначення, яке створює новий об'єкт списку, що містить ці чотири цілі числа, і присвоює йому посилання на цей об'єкт c. c1=c- це призначення, яке посилається на один і той же об'єкт і призначає цьому c1. Оскільки список є змінним, все, що трапляється із цим списком, буде видно незалежно від того, ви отримаєте доступ до нього через cабоc1 , що вони обидва посилаються на один і той же об’єкт.

c1=copy.copy(c)це "неглибока копія", яка створює новий список і присвоює посилання на новий список c1. cяк і раніше вказує на оригінальний список. Отже, якщо ви змінили список на c1, список, на який cпосилається, не зміниться.

Поняття копіювання не має відношення до незмінних об'єктів, таких як цілі числа та рядки. Оскільки ви не можете змінювати ці об'єкти, ніколи не потрібно мати дві копії одного і того ж значення в пам'яті в різних місцях. Отже цілі числа та рядки та деякі інші об'єкти, до яких поняття копіювання не застосовується, просто перепризначаються. Ось чому ваші приклади з aі bпризводять до однакових ідентифікаторів.

c1=copy.deepcopy(c)є "глибокою копією", але вона функціонує так само, як дрібну копію в цьому прикладі. Глибокі копії відрізняються від дрібних копій тим, що дрібні копії стануть новою копією самого об'єкта, але будь-які посилання всередині цього об’єкта самі по собі не будуть скопійовані. У вашому прикладі у вашому списку є лише цілі числа (які незмінні), і як уже було обговорено, копіювати їх не потрібно. Тож "глибока" частина глибокої копії не застосовується. Однак розглянемо цей більш складний перелік:

e = [[1, 2],[4, 5, 6],[7, 8, 9]]

Це список, який містить інші списки (ви також можете описати його як двовимірний масив).

Якщо ви запустите "дрібну копію" e, скопіювавши її e1, ви побачите, що ідентифікатор списку змінюється, але кожна копія списку містить посилання на ті самі три списки - списки з цілими числами всередині. Це означає, що якби ти це робив e[0].append(3), то eбув би [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Але e1також було б [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. З іншого боку, якби ви згодом це зробили e.append([10, 11, 12]), eбуло б [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Алеe1 все одно було б [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Це тому, що зовнішні списки - це окремі об'єкти, які спочатку містять по три посилання на три внутрішні списки. Якщо ви змінюєте внутрішні списки, ви можете бачити ці зміни незалежно від того, переглядаєте ви їх через одну чи іншу копію. Але якщо ви зміните один із зовнішніх списків, як зазначено вище, тоeмістить три посилання на три оригінальних списки плюс ще одне посилання на новий список. І e1досі містить лише оригінальні три посилання.

"Поглиблена копія" не тільки дублюватиме зовнішній список, але й буде проходити всередині списків та дублювати внутрішні списки, щоб два результуючі об'єкти не містили жодних однакових посилань (що стосується змінних об'єктів) . Якби внутрішні списки мали додаткові списки (або інші об'єкти, такі як словники) всередині них, вони теж дублювалися. Це "глибока" частина "глибокої копії".


2

У python, коли ми присвоюємо такі об'єкти, як list, кортежі, dict тощо, іншому об'єкту, як правило, зі знаком '=', python створює копії за посиланням . Тобто, скажімо, у нас є такий перелік:

list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ]  ]

і ми присвоюємо інший список цьому списку, як:

list2 = list1

то якщо ми надрукуємо list2 в терміналі python, ми отримаємо це:

list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]

Обидва list1 та list2 вказують на одне місце пам’яті, будь-яка зміна будь-якого з них призведе до змін, видимих ​​для обох об’єктів, тобто обидва об’єкти вказують на одне місце пам’яті. Якщо ми змінимо list1 так:

list1[0][0] = 'x’
list1.append( [ 'g'] )

тоді і list1, і list2 будуть:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g’ ] ]

Тепер, переходячи до Дрібної копії , коли два об’єкти скопійовані за допомогою дрібної копії, дочірній об’єкт обох батьківських об'єктів відноситься до одного місця пам’яті, але будь-які подальші нові зміни будь-якого скопійованого об’єкта будуть незалежними один від одного. Розберемося це на невеликому прикладі. Припустимо, у нас є цей невеликий фрагмент коду:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]      # assigning a list
list2 = copy.copy(list1)       # shallow copy is done using copy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

зауважте, list2 залишається незмінним, але якщо ми вносимо зміни до дочірніх об'єктів, наприклад:

list1[0][0] = 'x’

тоді і list1, і list2 отримають зміни:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]

Тепер глибока копія допомагає створювати повністю ізольовані об'єкти один від одного. Якщо два об'єкти скопійовано за допомогою Deep Copy, обидва батьків та його дитини будуть вказувати на інше місце пам'яті. Приклад:

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]         # assigning a list
list2 = deepcopy.copy(list1)       # deep copy is done using deepcopy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

зауважте, list2 залишається незмінним, але якщо ми вносимо зміни до дочірніх об'єктів, наприклад:

list1[0][0] = 'x’

тоді також list2 не вплине, оскільки всі дочірні об’єкти та батьківський об'єкт вказують на різні місця пам'яті:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f  ' ] ]

Сподіваюся, це допомагає.


0

Нижче код демонструє різницю між призначенням, дрібною копією методом копіювання, дрібною копією за допомогою (фрагмента) [:] та глибокої копії. Нижче приклад використовує там вкладені списки, роблячи відмінності більш очевидними.

from copy import deepcopy

########"List assignment (does not create a copy) ############
l1 = [1,2,3, [4,5,6], [7,8,9]]
l1_assigned = l1

print(l1)
print(l1_assigned)

print(id(l1), id(l1_assigned))
print(id(l1[3]), id(l1_assigned[3]))
print(id(l1[3][0]), id(l1_assigned[3][0]))

l1[3][0] = 100
l1.pop(4)
l1.remove(1)


print(l1)
print(l1_assigned)
print("###################################")

########"List copy using copy method (shallow copy)############

l2 = [1,2,3, [4,5,6], [7,8,9]]
l2_copy = l2.copy()

print(l2)
print(l2_copy)

print(id(l2), id(l2_copy))
print(id(l2[3]), id(l2_copy[3]))
print(id(l2[3][0]), id(l2_copy[3][0]))
l2[3][0] = 100
l2.pop(4)
l2.remove(1)


print(l2)
print(l2_copy)

print("###################################")

########"List copy using slice (shallow copy)############

l3 = [1,2,3, [4,5,6], [7,8,9]]
l3_slice = l3[:]

print(l3)
print(l3_slice)

print(id(l3), id(l3_slice))
print(id(l3[3]), id(l3_slice[3]))
print(id(l3[3][0]), id(l3_slice[3][0]))

l3[3][0] = 100
l3.pop(4)
l3.remove(1)


print(l3)
print(l3_slice)

print("###################################")

########"List copy using deepcopy ############

l4 = [1,2,3, [4,5,6], [7,8,9]]
l4_deep = deepcopy(l4)

print(l4)
print(l4_deep)

print(id(l4), id(l4_deep))
print(id(l4[3]), id(l4_deep[3]))
print(id(l4[3][0]), id(l4_deep[3][0]))

l4[3][0] = 100
l4.pop(4)
l4.remove(1)

print(l4)
print(l4_deep)
print("##########################")
print(l4[2], id(l4[2]))
print(l4_deep[3], id(l4_deep[3]))

print(l4[2][0], id(l4[2][0]))
print(l4_deep[3][0], id(l4_deep[3][0]))

0

ГІСТ, який потрібно взяти, такий: спрацьовування з неглибокими списками (немає під-списків, лише окремі елементи) за допомогою "нормального призначення" викликає "побічний ефект", коли ви створюєте неглибокий список, а потім створюєте копію цього списку за допомогою "звичайного призначення" . Цей "побічний ефект" - це коли ви змінюєте будь-який елемент створеного списку копій, оскільки він автоматично змінить ті самі елементи вихідного списку. Це copyстане в нагоді, оскільки воно не змінить оригінальні елементи списку при зміні елементів копіювання.

З іншого боку, copyчи має "побічний ефект", коли у вас є список, який містить списки в ньому (під-списки), і deepcopyвирішує його. Наприклад, якщо ви створюєте великий список із вкладеними списками в ньому (під-списки), і ви створюєте копію цього великого списку (оригінальний список). "Побічний ефект" виникає, коли ви змінюєте під-списки списку копій, які автоматично змінюють під-списки великого списку. Іноді (в деяких проектах) ви хочете зберегти великий список (ваш оригінальний список) таким, який він є без змін, і все, що вам потрібно, - це зробити копію його елементів (під-списків). Для цього ваше рішення полягає в тому, щоб скористатися deepcopyцим "побічним ефектом" і зробити копію, не змінюючи оригінальний вміст.

Різне поведінка copyта deep copyоперації стосуються лише складних об'єктів (тобто об'єктів, що містять інші об'єкти, такі як списки).

Ось відмінності, проілюстровані в цьому простому прикладі коду:

Перший

давайте перевіримо, як copyповодиться (неглибоко), створивши оригінальний список та копію цього списку:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Тепер давайте проведемо кілька printтестів і подивимося, як поводиться оригінальний список порівняно зі списком його копій:

original_list та copy_list мають різні адреси

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

елементи original_list та copy_list мають однакові адреси

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

підменю елементів original_list та copy_list мають однакові адреси

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08

зміна елементів original_list НЕ змінює елементи copy_list

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

зміна елементів copy_list НЕ змінює елементи original_list

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

зміна оригінального_подмета_елементів автоматично модифікує під_елементи copy_list

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]

зміна під_елементів copy_list автоматично змінює под_елементи original_list

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]

Друге

давайте перевіримо, як deepcopyповодиться, зробивши те саме, що ми зробили copy(створивши оригінальний список та копію цього списку):

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

Тепер давайте проведемо кілька printтестів і подивимося, як поводиться оригінальний список порівняно зі списком його копій:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)

original_list та copy_list мають різні адреси

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

елементи original_list та copy_list мають однакові адреси

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

підменю елементів original_list та copy_list мають різні адреси

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300

зміна елементів original_list НЕ змінює елементи copy_list

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

зміна елементів copy_list НЕ змінює елементи original_list

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

зміна original_list sub_elements НЕ змінює copy_list sub_elements

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

зміна sub_elements copy_list НЕ змінює под_елементи original_list

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]

0

Не впевнений, чи згадувалося вище чи ні, але дуже важливо відмовитись від того, що .copy () створить посилання на оригінальний об'єкт. Якщо ви змінюєте скопійований об'єкт - ви змінюєте оригінальний об'єкт. .deepcopy () створює новий об'єкт і робить реальну копію оригінального об'єкта на новий. Зміна нового глибококопійованого об'єкта не впливає на оригінальний об'єкт.

І так.

Отже різниця в копіюванні / посиланні між .copy () і .deepcopy () є значною.


0

Глибока копія пов'язана з вкладеними структурами. Якщо у вас є список списків, то глибока копія також копіює вкладені списки, тож це рекурсивна копія. За допомогою лише копії у вас є новий зовнішній список, але внутрішні списки - це посилання. Призначення не копіюється. Для екс

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.copy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

OutPut

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Метод копіювання копіює вміст зовнішнього списку в новий список, але внутрішнього списку є як і раніше для обох списків, тому якщо ви внесете зміни у внутрішній список будь-якого списку, це вплине на обидва списки.

Але якщо ви використовуєте Deep copy, то це створить новий екземпляр і для внутрішнього списку.

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.deepcopy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

Вихідні дані

[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]


-1
>>lst=[1,2,3,4,5]

>>a=lst

>>b=lst[:]

>>> b
[1, 2, 3, 4, 5]

>>> a
[1, 2, 3, 4, 5]

>>> lst is b
False

>>> lst is a
True

>>> id(lst)
46263192

>>> id(a)
46263192 ------>  See here id of a and id of lst is same so its called deep copy and even boolean answer is true

>>> id(b)
46263512 ------>  See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.

a не є глибокою копією lst !
Георгій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.