Qual è la differenza tra copia superficiale, deepcopy e normale operazione di assegnazione?


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

Ottengo i seguenti risultati:

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

Se eseguo deepcopy:

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

i risultati sono gli stessi:

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

Se lavoro nelle operazioni di assegnazione:

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

quindi i risultati sono:

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

Qualcuno può spiegare cosa fa esattamente la differenza tra le copie? È qualcosa in relazione con oggetti mutabili e immutabili? Se è così, puoi spiegarmelo, per favore?

Risposte:


364

Le normali operazioni di assegnazione punteranno semplicemente la nuova variabile verso l'oggetto esistente. I documenti spiegano la differenza tra copie superficiali e profonde:

La differenza tra copia superficiale e profonda è rilevante solo per gli oggetti composti (oggetti che contengono altri oggetti, come elenchi o istanze di classe):

  • Una copia superficiale costruisce un nuovo oggetto composto e quindi (per quanto possibile) inserisce riferimenti in esso agli oggetti trovati nell'originale.

  • Una copia profonda costruisce un nuovo oggetto composto e quindi, ricorsivamente, inserisce copie degli oggetti trovati nell'originale.

Ecco una piccola dimostrazione:

import copy

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

Utilizzo delle normali operazioni di assegnazione per copiare:

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]

Utilizzando una copia superficiale:

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]

Utilizzando una copia profonda:

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
l'assginment è uguale alla copia superficiale?
Deeshank,

35
@ Dshank No. Una copia superficiale costruisce un nuovo oggetto, mentre un'assegnazione punterà semplicemente la nuova variabile sull'oggetto esistente. Qualsiasi modifica all'oggetto esistente influenzerà entrambe le variabili (con assegnazione).
GRC,

13
@grc "Qualsiasi modifica all'oggetto esistente influenzerà entrambe le variabili (con assegnazione)" - questa affermazione è vera solo per oggetti mutabili e non per tipi immutabili come stringa, float, tuple.
Neerav,

1
@grc Ma ho provato un esempio (rimuovo qui la nuova riga.) list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)Il newlistdisplay fisso [[1, 2], [3, 4]]. Ma list_[0]è un elenco mutabile.
Alston,

1
@Stallman list_[0]è mutabile, ma non lo stai modificando / modificando. Prova list_[0].append(9)o list_[0][0] = 7invece.
grc,

46

Per oggetti immutabili, non è necessario copiare perché i dati non cambieranno mai, quindi Python utilizza gli stessi dati; gli ID sono sempre gli stessi. Per oggetti mutabili, poiché possono potenzialmente cambiare, la copia [superficiale] crea un nuovo oggetto.

La copia profonda è correlata alle strutture nidificate. Se si dispone di un elenco di elenchi, quindi deepcopycopies gli elenchi nidificati, quindi è una copia ricorsiva. Con solo copia, hai un nuovo elenco esterno, ma gli elenchi interni sono riferimenti.

L'assegnazione non viene copiata. Imposta semplicemente il riferimento ai vecchi dati. Quindi è necessario copiare per creare un nuovo elenco con gli stessi contenuti.


With just copy, you have a new outer list but inner lists are references.Per le liste interne, quella copiata sarebbe influenzata da quella originale? Creo un elenco di elenchi come list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]e il newlistresto è lo stesso, quindi l'elenco interno sono riferimenti?
Alston,

1
@Stallman non stai modificando l'elenco di riferimento qui, ma semplicemente creando un nuovo elenco e assegnandolo come primo elemento di una delle copie. prova a farelist_[0][0] = 7
perreal

20

Per oggetti immutabili, creare una copia non ha molto senso poiché non cambieranno. Per oggetti mutabili assignment, copye deepcopysi comporta diversamente. Parliamo di ciascuno di essi con esempi.

Un'operazione di assegnazione assegna semplicemente il riferimento della sorgente alla destinazione, ad esempio:

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

Ora ie jtecnicamente si riferisce allo stesso elenco. Entrambi ie jhanno lo stesso indirizzo di memoria. Qualsiasi aggiornamento a uno di essi si rifletterà sull'altro. per esempio:

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

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

D'altra parte copye deepcopycrea una nuova copia della variabile. Quindi ora le modifiche alla variabile originale non si rifletteranno sulla variabile copia e viceversa. peròcopy(shallow copy) , non crea una copia di oggetti nidificati, ma copia semplicemente il riferimento di oggetti nidificati. Deepcopy copia tutti gli oggetti nidificati in modo ricorsivo.

Alcuni esempi per dimostrare il comportamento di copye deepcopy:

Esempio di elenco semplice usando 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

Esempio di elenco nidificato utilizzando 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

Esempio di elenco semplice usando 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

Esempio di elenco nidificato utilizzando 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

Vediamo in un esempio grafico come viene eseguito il seguente codice:

import copy

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


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

inserisci qui la descrizione dell'immagine


5

a, b, c, d, a1, b1, c1 e d1 sono riferimenti a oggetti in memoria, identificati in modo univoco dai loro ID.

Un'operazione di assegnazione prende un riferimento all'oggetto in memoria e assegna quel riferimento a un nuovo nome. c=[1,2,3,4]è un compito che crea un nuovo oggetto elenco contenente quei quattro numeri interi e assegna il riferimento a quell'oggetto c. c1=cè un compito che accetta lo stesso riferimento allo stesso oggetto e lo assegna a c1. Poiché l'elenco è modificabile, tutto ciò che accade a tale elenco sarà visibile indipendentemente dal fatto che si acceda tramite coc1 , poiché entrambi fanno riferimento allo stesso oggetto.

c1=copy.copy(c)è una "copia superficiale" che crea un nuovo elenco e assegna il riferimento al nuovo elenco c1. cpunta ancora all'elenco originale. Pertanto, se si modifica l'elenco in c1, l'elenco a cui si cfa riferimento non cambierà.

Il concetto di copia è irrilevante per oggetti immutabili come numeri interi e stringhe. Poiché non è possibile modificare tali oggetti, non è mai necessario avere due copie dello stesso valore in memoria in posizioni diverse. Quindi numeri interi e stringhe, e alcuni altri oggetti a cui non si applica il concetto di copia, vengono semplicemente riassegnati. Questo è il motivo per cui i tuoi esempi con ae brisultano identici ID.

c1=copy.deepcopy(c)è una "copia profonda", ma funziona come una copia superficiale in questo esempio. Le copie profonde differiscono dalle copie superficiali in quanto le copie superficiali faranno una nuova copia dell'oggetto stesso, ma tutti i riferimenti all'interno di tale oggetto non verranno copiati. Nel tuo esempio, la tua lista contiene solo numeri interi (che sono immutabili), e come precedentemente discusso non è necessario copiarli. Quindi la parte "profonda" della copia profonda non si applica. Tuttavia, considera questo elenco più complesso:

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

Questo è un elenco che contiene altri elenchi (potresti anche descriverlo come un array bidimensionale).

Se esegui una "copia superficiale" su e, copiandola e1, scoprirai che l'id dell'elenco cambia, ma ogni copia dell'elenco contiene riferimenti agli stessi tre elenchi - gli elenchi con numeri interi all'interno. Ciò significa che se dovessi farlo e[0].append(3), lo esarebbe [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Ma e1sarebbe anche [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. D'altra parte, se lo facessi successivamente e.append([10, 11, 12]), lo esarebbe [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Ma e1sarebbe ancora [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Questo perché gli elenchi esterni sono oggetti separati che inizialmente contengono ciascuno tre riferimenti a tre elenchi interni. Se si modificano gli elenchi interni, è possibile visualizzare tali modifiche indipendentemente dal fatto che vengano visualizzate in una copia o nell'altra. Ma se modifichi una delle liste esterne come sopra, allorae contenere tre riferimenti alle tre liste originali più un altro riferimento a una nuova lista. E e1contiene ancora solo i tre riferimenti originali.

Una 'copia profonda' non solo duplica l'elenco esterno, ma va anche all'interno degli elenchi e duplica gli elenchi interni, in modo che i due oggetti risultanti non contengano nessuno degli stessi riferimenti (per quanto riguarda gli oggetti mutabili) . Se gli elenchi interni contenessero ulteriori elenchi (o altri oggetti come dizionari) al loro interno, anche questi sarebbero duplicati. Questa è la parte "profonda" della "copia profonda".


2

In python, quando assegniamo oggetti come list, tuples, dict, ecc a un altro oggetto solitamente con un segno '=', python crea copie per riferimento . Cioè, supponiamo di avere un elenco di elenchi come questo:

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

e assegniamo un altro elenco a questo elenco come:

list2 = list1

quindi se stampiamo list2 nel terminale Python otterremo questo:

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

Sia list1 che list2 puntano alla stessa posizione di memoria, qualsiasi modifica a una qualsiasi di esse comporterà modifiche visibili in entrambi gli oggetti, ovvero entrambi gli oggetti puntano alla stessa posizione di memoria. Se cambiamo list1 in questo modo:

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

quindi sia list1 che list2 saranno:

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

Ora arriviamo alla copia superficiale , quando due oggetti vengono copiati tramite copia superficiale, l'oggetto figlio di entrambi gli oggetti padre fa riferimento alla stessa posizione di memoria, ma qualsiasi ulteriore nuova modifica in uno qualsiasi degli oggetti copiati sarà indipendente l'una dall'altra. Comprendiamolo con un piccolo esempio. Supponiamo di avere questo piccolo frammento di codice:

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

notate, list2 rimane inalterato, ma se apportiamo modifiche a oggetti figlio come:

list1[0][0] = 'x’

quindi sia list1 che list2 avranno il resto:

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

Ora, Deep copy aiuta a creare oggetti completamente isolati l'uno dall'altro. Se due oggetti vengono copiati tramite Deep Copy, sia il genitore che il figlio indicheranno una diversa posizione di memoria. Esempio :

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

notate, list2 rimane inalterato, ma se apportiamo modifiche a oggetti figlio come:

list1[0][0] = 'x’

quindi anche list2 non sarà influenzato dal momento che tutti gli oggetti figlio e l'oggetto padre puntano a posizioni di memoria diverse:

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

Spero che sia d'aiuto.


0

Il codice seguente mostra la differenza tra assegnazione, copia superficiale usando il metodo copia, copia superficiale usando (slice) [:] e la copia profonda. L'esempio seguente utilizza elenchi nidificati lì rendendo le differenze più evidenti.

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

Il GIST da prendere è questo: trattare con liste poco profonde (senza liste secondarie, solo singoli elementi) usando "assegnazione normale" genera un "effetto collaterale" quando si crea una lista superficiale e quindi si crea una copia di questa lista usando "assegnazione normale" . Questo "effetto collaterale" si verifica quando si modifica qualsiasi elemento dell'elenco copie creato, poiché cambierà automaticamente gli stessi elementi dell'elenco originale. Questo è copyutile quando non cambia gli elementi dell'elenco originale quando si cambiano gli elementi della copia.

D'altra parte, copyha anche un "effetto collaterale", quando si dispone di un elenco che contiene elenchi (elenchi secondari) e lo deepcopyrisolve. Ad esempio, se si crea un grande elenco che contiene elenchi nidificati (elenchi secondari) e si crea una copia di questo grande elenco (l'elenco originale). L '"effetto collaterale" si presenterebbe quando si modificano le liste secondarie dell'elenco copie che modifica automaticamente le liste secondarie dell'elenco grande. A volte (in alcuni progetti) vuoi mantenere la grande lista (la tua lista originale) così com'è senza modifiche, e tutto ciò che vuoi è fare una copia dei suoi elementi (sub_lists). Per questo, la tua soluzione è utilizzare deepcopyche si occuperà di questo "effetto collaterale" e ne farà una copia senza modificare il contenuto originale.

I diversi comportamenti copye deep copyoperazioni riguardano solo oggetti composti (ovvero: oggetti che contengono altri oggetti come gli elenchi).

Ecco le differenze illustrate in questo semplice esempio di codice:

Primo

controlliamo come copysi comporta (superficiale) creando un elenco originale e una copia di questo elenco:

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

Ora, eseguiamo alcuni printtest e vediamo come si comporta l'elenco originale rispetto al suo elenco di copie:

original_list e copy_list hanno indirizzi diversi

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

gli elementi di original_list e copy_list hanno gli stessi indirizzi

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

gli elementi secondari di original_list e copy_list hanno gli stessi indirizzi

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

la modifica degli elementi original_list NON modifica gli elementi 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 modifica degli elementi copy_list NON modifica gli elementi 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]

modifica original_list sub_elements modifica automaticamente 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', 'c'], 7]

modifica copy_list sub_elements modifica automaticamente 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', 'c', 'd'], 7]

Secondo

controlliamo come deepcopysi comporta, facendo la stessa cosa che abbiamo fatto con copy(creando un elenco originale e una copia di questo elenco):

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

Ora, eseguiamo alcuni printtest e vediamo come si comporta l'elenco originale rispetto al suo elenco di copie:

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

original_list e copy_list hanno indirizzi diversi

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

gli elementi di original_list e copy_list hanno gli stessi indirizzi

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

gli elementi secondari di original_list e copy_list hanno indirizzi diversi

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

la modifica degli elementi original_list NON modifica gli elementi 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 modifica degli elementi copy_list NON modifica gli elementi 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 modifica di original_list sub_elements NON modifica 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]

la modifica di copy_list sub_elements NON modifica 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

Non sono sicuro se menzionato sopra o no, ma è molto difficile capire che .copy () crea un riferimento all'oggetto originale. Se si modifica l'oggetto copiato, si modifica l'oggetto originale. .deepcopy () crea un nuovo oggetto ed esegue una copia reale dell'oggetto originale su uno nuovo. La modifica di un nuovo oggetto deepcopied non influisce sull'oggetto originale.

E sì, .deepcopy () copia ricorsivamente l'oggetto originale, mentre .copy () crea un oggetto di riferimento ai dati di primo livello dell'oggetto originale.

Pertanto, la differenza di copia / riferimento tra .copy () e .deepcopy () è significativa.


0

La copia profonda è correlata alle strutture nidificate. Se hai un elenco di elenchi, copia in profondità anche gli elenchi nidificati, quindi è una copia ricorsiva. Con solo copia, hai un nuovo elenco esterno, ma gli elenchi interni sono riferimenti. L'assegnazione non viene copiata. Per es

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

Produzione

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Copia metodo copia dell'elenco esterno in un nuovo elenco ma l'elenco interno è sempre lo stesso per entrambi gli elenchi, quindi se si apportano modifiche all'elenco interno di qualsiasi elenco, ciò influirà su entrambi gli elenchi.

Ma se usi Deep copy, creerà anche una nuova istanza per l'elenco interno.

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

Produzione

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

anon è un deepcopy di lst!
Georgy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.