Quelle est la différence entre une copie superficielle, une copie profonde et une opération d'affectation normale?

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

J'obtiens les résultats suivants:

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

Si j'effectue une copie profonde:

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

les résultats sont les mêmes:

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

Si je travaille sur des opérations d'affectation:

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

alors les résultats sont:

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

Quelqu'un peut-il expliquer ce qui fait exactement la différence entre les copies? Est-ce quelque chose lié aux objets mutables et immuables? Si oui, pouvez-vous me l'expliquer?

deeshank
la source

Réponses:

364

Les opérations d'affectation normales pointeront simplement la nouvelle variable vers l'objet existant. Les documents expliquent la différence entre les copies peu profondes et les copies profondes:

La différence entre la copie superficielle et la copie profonde n'est pertinente que pour les objets composés (objets qui contiennent d'autres objets, comme des listes ou des instances de classe):

  • Une copie superficielle construit un nouvel objet composé, puis (dans la mesure du possible) y insère des références aux objets trouvés dans l'original.

  • Une copie profonde construit un nouvel objet composé, puis, récursivement, y insère des copies des objets trouvés dans l'original.

Voici une petite démonstration:

import copy

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

Utilisation des opérations d'affectation normales pour copier:

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]

En utilisant une copie superficielle:

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]

Utilisation d'une copie complète:

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
grc
la source
5
l'assignation est-elle la même que la copie superficielle?
deeshank
35
@Dshank No. Une copie superficielle construit un nouvel objet, tandis qu'une affectation pointe simplement la nouvelle variable vers l'objet existant. Toute modification de l'objet existant affectera les deux variables (avec affectation).
grc
13
@grc "Toute modification apportée à l'objet existant affectera les deux variables (avec affectation)" - cette déclaration est vraie uniquement pour les objets mutables et non pour les types immuables tels que chaîne, flottant, tuples.
Neerav
1
@grc Mais j'ai essayé un exemple (je supprime la nouvelle ligne ici.) list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)L' newlistaffichage fixe [[1, 2], [3, 4]]. Mais list_[0]c'est une liste qui est mutable.
Alston
1
@Stallman list_[0]est modifiable, mais vous ne le mutez / modifiez pas. Essayez list_[0].append(9)ou à la list_[0][0] = 7place.
grc
46

Pour les objets immuables, il n'est pas nécessaire de copier car les données ne changeront jamais, donc Python utilise les mêmes données; les identifiants sont toujours les mêmes. Pour les objets mutables, car ils peuvent potentiellement changer, la copie [superficielle] crée un nouvel objet.

La copie profonde est liée aux structures imbriquées. Si vous avez une liste de listes, alors deepcopycopies également en les listes imbriquées, il s'agit donc d'une copie récursive. Avec juste copier, vous avez une nouvelle liste externe, mais les listes internes sont des références.

L'affectation n'est pas copiée. Il définit simplement la référence aux anciennes données. Vous devez donc copier pour créer une nouvelle liste avec le même contenu.

perreal
la source
With just copy, you have a new outer list but inner lists are references.Pour les listes internes, celle copiée serait-elle influencée par la liste originale? Je crée une liste de listes comme list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]et la newlistreste la même, donc la liste intérieure est-elle une référence?
Alston
1
@Stallman, vous ne modifiez pas la liste référencée ici, créez simplement une nouvelle liste et affectez-la comme premier élément de l'une des copies. essayez de fairelist_[0][0] = 7
perreal
20

Pour les objets immuables, créer une copie n'a pas beaucoup de sens car ils ne vont pas changer. Pour les objets mutables assignment, copyet deepcopyse comporte différemment. Permet de parler de chacun d'eux avec des exemples.

Une opération d'assignation affecte simplement la référence de la source à la destination, par exemple:

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

Désigne maintenant iet jtechniquement la même liste. Les deux iet jont la même adresse mémoire. Toute mise à jour de l'un d'eux sera répercutée sur l'autre. par exemple:

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

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

D'autre part copyet deepcopycrée une nouvelle copie de variable. Les modifications apportées à la variable d'origine ne seront donc plus répercutées sur la variable de copie et vice versa. Cependant copy(shallow copy), ne crée pas de copie des objets imbriqués, mais copie simplement la référence des objets imbriqués. Deepcopy copie tous les objets imbriqués de manière récursive.

Quelques exemples pour démontrer le comportement de copyet deepcopy:

Exemple de liste plate utilisant 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

Exemple de liste imbriquée utilisant 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

Exemple de liste plate utilisant 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

Exemple de liste imbriquée utilisant 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    
Sohaib Farooqi
la source
18

Voyons dans un exemple graphique comment le code suivant est exécuté:

import copy

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


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

entrez la description de l'image ici

user1767754
la source
5

a, b, c, d, a1, b1, c1 et d1 sont des références à des objets en mémoire, qui sont uniquement identifiés par leurs identifiants.

Une opération d'affectation prend une référence à l'objet en mémoire et affecte cette référence à un nouveau nom. c=[1,2,3,4]est une affectation qui crée un nouvel objet de liste contenant ces quatre entiers et affecte la référence à cet objet c. c1=cest une affectation qui prend la même référence au même objet et l'affecte à c1. Étant donné que la liste est modifiable, tout ce qui arrive à cette liste sera visible, que vous y accédiez via cou c1, car ils font tous deux référence au même objet.

c1=copy.copy(c)est une "copie superficielle" qui crée une nouvelle liste et affecte la référence à la nouvelle liste c1. cpointe toujours vers la liste d'origine. Donc, si vous modifiez la liste à c1, la liste à laquelle vous vous référez cne changera pas.

Le concept de copie n'est pas pertinent pour les objets immuables comme les entiers et les chaînes. Comme vous ne pouvez pas modifier ces objets, il n'est jamais nécessaire d'avoir deux copies de la même valeur en mémoire à différents emplacements. Les entiers et les chaînes, ainsi que certains autres objets auxquels le concept de copie ne s'applique pas, sont simplement réaffectés. C'est pourquoi vos exemples avec aet baboutissent à des identifiants identiques.

c1=copy.deepcopy(c)est une "copie complète", mais elle fonctionne de la même manière qu'une copie superficielle dans cet exemple. Les copies profondes diffèrent des copies superficielles en ce que les copies superficielles feront une nouvelle copie de l'objet lui-même, mais toutes les références à l' intérieur de cet objet ne seront pas elles-mêmes copiées. Dans votre exemple, votre liste ne contient que des entiers (qui sont immuables), et comme nous l'avons vu précédemment, il n'est pas nécessaire de les copier. La partie "profonde" de la copie profonde ne s'applique donc pas. Cependant, considérez cette liste plus complexe:

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

Il s'agit d'une liste qui contient d'autres listes (vous pouvez également la décrire comme un tableau à deux dimensions).

Si vous exécutez une "copie superficielle" sur e, en la copiant e1, vous constaterez que l'id de la liste change, mais chaque copie de la liste contient des références aux trois mêmes listes - les listes avec des nombres entiers à l'intérieur. Cela signifie que si vous deviez le faire e[0].append(3), ce eserait le cas [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Mais le e1serait aussi [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. D'un autre côté, si vous l'avez fait par la suite e.append([10, 11, 12]), ce eserait le cas [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Mais e1serait toujours[[1, 2, 3],[4, 5, 6],[7, 8, 9]] . En effet, les listes externes sont des objets distincts qui contiennent initialement chacun trois références à trois listes internes. Si vous modifiez les listes internes, vous pouvez voir ces changements, que vous les consultiez sur une copie ou sur l'autre. Mais si vous modifiez l'une des listes externes comme ci-dessus, alorsecontient trois références aux trois listes d'origine plus une référence à une nouvelle liste. Et e1ne contient toujours que les trois références originales.

Une `` copie en profondeur '' non seulement dupliquerait la liste externe, mais elle irait également à l'intérieur des listes et dupliquerait les listes internes, de sorte que les deux objets résultants ne contiennent aucune des mêmes références (en ce qui concerne les objets mutables) . Si les listes internes avaient d'autres listes (ou d'autres objets tels que des dictionnaires) à l'intérieur, elles seraient également dupliquées. C'est la partie «profonde» de la «copie profonde».

Andrew Gorcester
la source
2

En python, lorsque nous assignons des objets comme list, tuples, dict, etc. à un autre objet généralement avec un signe '=', python crée des copies par référence . Autrement dit, disons que nous avons une liste de liste comme celle-ci:

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

et nous attribuons une autre liste à cette liste comme:

list2 = list1

alors si nous imprimons list2 dans le terminal python, nous obtiendrons ceci:

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

List1 et list2 pointent tous les deux vers le même emplacement mémoire, toute modification apportée à l'un d'eux entraînera des changements visibles dans les deux objets, c'est-à-dire que les deux objets pointent vers le même emplacement mémoire. Si nous changeons list1 comme ceci:

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

alors list1 et list2 seront:

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

Maintenant à la copie peu profonde , lorsque deux objets sont copiés via une copie superficielle, l'objet enfant des deux objets parents fait référence au même emplacement de mémoire, mais toute nouvelle modification dans l'un des objets copiés sera indépendante l'une de l'autre. Comprenons cela avec un petit exemple. Supposons que nous ayons ce petit extrait de code:

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 '] ]

remarquez que list2 reste inchangé, mais si nous apportons des modifications aux objets enfants comme:

list1[0][0] = 'x’

alors list1 et list2 obtiendront des modifications:

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

Maintenant, copie profonde permet de créer des objets complètement isolés les uns des autres. Si deux objets sont copiés via Deep Copy, le parent et son enfant pointeront vers un emplacement mémoire différent. Exemple :

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 '] ]

remarquez que list2 reste inchangé, mais si nous apportons des modifications aux objets enfants comme:

list1[0][0] = 'x’

alors list2 ne sera pas affecté car tous les objets enfants et objets parents pointent vers un emplacement mémoire différent:

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

J'espère que ça aide.

Nitish Chauhan
la source
0

Le code ci-dessous montre la différence entre l'affectation, la copie superficielle à l'aide de la méthode de copie, la copie superficielle à l'aide de la (tranche) [:] et la copie profonde. L'exemple ci-dessous utilise des listes imbriquées en rendant les différences plus évidentes.

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]))
Sandeep
la source
0

Le GIST à prendre est le suivant: Traiter des listes superficielles (pas de sous-listes, juste des éléments simples) en utilisant une «affectation normale» augmente un «effet secondaire» lorsque vous créez une liste peu profonde, puis vous créez une copie de cette liste en utilisant une «affectation normale» . Cet "effet secondaire" survient lorsque vous modifiez un élément de la liste de copie créée, car il modifie automatiquement les mêmes éléments de la liste d'origine. C'est quand cela copyest pratique, car cela ne changera pas les éléments de la liste d'origine lors du changement des éléments de copie.

D'un autre côté, copycela a également un "effet secondaire" lorsque vous avez une liste qui contient des listes (sub_lists) et la deepcopyrésout. Par exemple, si vous créez une grande liste contenant des listes imbriquées (sub_lists) et que vous créez une copie de cette grande liste (la liste d'origine). L '«effet secondaire» se produirait lorsque vous modifiez les sous-listes de la liste de copie, ce qui modifierait automatiquement les sous-listes de la grande liste. Parfois (dans certains projets), vous souhaitez conserver la grande liste (votre liste d'origine) telle qu'elle est sans modification, et tout ce que vous voulez, c'est faire une copie de ses éléments (sub_lists). Pour cela, votre solution est d'utiliser deepcopyce qui va prendre en charge cet "effet secondaire" et en faire une copie sans modifier le contenu d'origine.

Les différents comportements copyet deep copyopérations ne concernent que les objets composés (c'est-à-dire les objets qui contiennent d'autres objets tels que des listes).

Voici les différences illustrées dans cet exemple de code simple:

Première

vérifions le copycomportement (superficiel), en créant une liste originale et une copie de cette liste:

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

Maintenant, exécutons quelques printtests et voyons comment la liste d'origine se comporte par rapport à sa liste de copie:

original_list et copy_list ont des adresses différentes

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

les éléments de original_list et copy_list ont les mêmes adresses

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

les sous-éléments de original_list et copy_list ont les mêmes adresses

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

la modification des éléments original_list ne modifie PAS les éléments 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']]

la modification des éléments copy_list ne modifie PAS les éléments 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]

la modification des sous-éléments de la liste d'origine modifie automatiquement les sous-éléments de la liste de copie

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]

la modification des sous-éléments copy_list modifie automatiquement les sous-éléments 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]

Seconde

vérifions comment deepcopyse comporte, en faisant la même chose que nous avons fait avec copy(création d'une liste originale et d'une copie de cette liste):

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

Maintenant, exécutons quelques printtests et voyons comment la liste d'origine se comporte par rapport à sa liste de copie:

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

original_list et copy_list ont des adresses différentes

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

les éléments de original_list et copy_list ont les mêmes adresses

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

les sous-éléments de original_list et copy_list ont des adresses différentes

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

la modification des éléments original_list ne modifie PAS les éléments 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']]

la modification des éléments copy_list ne modifie PAS les éléments 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]

la modification des sous-éléments de la liste d'origine ne modifie PAS les sous-éléments de la copie_liste

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]

la modification des sous-éléments copy_list ne modifie PAS les sous-éléments 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]
Fouad Boukredine
la source
0

Je ne sais pas si cela est mentionné ci-dessus ou non, mais il est très importable de comprendre que .copy () crée une référence à l'objet d'origine. Si vous modifiez l'objet copié - vous modifiez l'objet d'origine. .deepcopy () crée un nouvel objet et effectue une copie réelle de l'objet d'origine vers un nouvel objet. La modification d'un nouvel objet copié en profondeur n'affecte pas l'objet d'origine.

Et oui, .deepcopy () copie récursivement l'objet d'origine, tandis que .copy () crée un objet de référence aux données de premier niveau de l'objet d'origine.

La différence de copie / référencement entre .copy () et .deepcopy () est donc significative.

rémort
la source
0

La copie profonde est liée aux structures imbriquées. Si vous avez une liste de listes, alors Deepcopy copie également les listes imbriquées, il s'agit donc d'une copie récursive. Avec juste copier, vous avez une nouvelle liste externe, mais les listes internes sont des références. L'affectation n'est pas copiée. Pour 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)

Production

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Méthode de copie copier le contenu de la liste externe vers la nouvelle liste mais la liste interne est toujours la même pour les deux listes, donc si vous apportez des modifications à la liste intérieure de toutes les listes, cela affectera les deux listes.

Mais si vous utilisez Deep Copy, cela créera également une nouvelle instance pour la liste interne.

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

Production

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

Shubham Agarwal
la source
-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.
sudhir tataraju
la source
an'est pas une copie profonde de lst!
Georgy