В чем разница между мелким копированием, глубокой копией и обычной операцией назначения?


211
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
такое назначение такое же как мелкая копия?
Deeshank

35
@Dshank Нет. Мелкая копия создает новый объект, в то время как присваивание просто укажет новую переменную на существующий объект. Любые изменения в существующем объекте будут влиять на обе переменные (с присваиванием).
grc

13
@grc «Любые изменения в существующем объекте будут влиять на обе переменные (с присваиванием)» - это утверждение верно только для изменяемых объектов и не неизменяемых типов, таких как string, float, tuples.
Нерав

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 использует те же данные; идентификаторы всегда одинаковы. Для изменчивых объектов, поскольку они могут потенциально изменяться, [мелкая] копия создает новый объект.

Глубокая копия связана с вложенными структурами. Если у вас есть список списков, то Deepcopycopies и вложенных списков, так что это рекурсивная копия. С помощью просто копирования у вас есть новый внешний список, но внутренние списки являются ссылками.

Назначение не копируется. Он просто устанавливает ссылку на старые данные. Поэтому вам нужно скопировать, чтобы создать новый список с тем же содержанием.


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
Perreal

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) , не создает копию вложенных объектов, вместо этого он просто копирует ссылку на вложенные объекты. Deepcopy рекурсивно копирует все вложенные объекты.

Некоторые примеры, демонстрирующие поведение 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, tuple, 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 помогает создавать совершенно изолированные объекты друг от друга. Если два объекта копируются с помощью 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также имеет «побочный эффект», когда у вас есть список, в котором есть списки (sub_lists), и deepcopyон решает его. Например, если вы создаете большой список, в котором есть вложенные списки (sub_lists), и вы создаете копию этого большого списка (исходный список). «Побочный эффект» возникает, когда вы изменяете подсписки списка копирования, которые автоматически изменяют подсписки большого списка. Иногда (в некоторых проектах) вы хотите сохранить большой список (ваш первоначальный список) без изменений, и все, что вам нужно, - это сделать копию его элементов (sub_lists). Для этого ваше решение заключается в использовании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

sub_elements of 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]

изменение sub_elements original_list автоматически изменяет sub_elements 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]

изменение sub_elements copy_list автоматически изменяет sub_elements 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

sub_elements в 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]

изменение copy_list sub_elements НЕ изменяет original_list sub_elements

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 () создает новый объект и выполняет реальное копирование исходного объекта в новый. Изменение нового глубоко скопированного объекта не влияет на исходный объект.

И да, .deepcopy () рекурсивно копирует исходный объект, а .copy () создает ссылочный объект для данных первого уровня исходного объекта.

Таким образом, разница между копированием и ссылками между .copy () и .deepcopy () значительна.


0

Глубокая копия связана с вложенными структурами. Если у вас есть список списков, то Deepcopy также копирует вложенные списки, поэтому это рекурсивная копия. С помощью просто копирования у вас есть новый внешний список, но внутренние списки являются ссылками. Назначение не копируется. Для Ex

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

Вывод

[[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.