2015-07-25 15 views
7

Capisco le differenze tra copia superficiale e copia profonda come ho imparato in classe. Tuttavia, il seguente non ha sensoCopia e DeepCopy in python3

import copy 

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

b = copy.deepcopy(a) 

print(a is b) 
print(a[0] is b[0]) 
---------------------------- 
~Output~ 
>False 
>True 
---------------------------- 

non print(a[0] is b[0]) dovrebbe valutare False come gli oggetti ed i loro elementi costitutivi vengono ricreati in una posizione di memoria diversa in una copia profonda? Stavo solo testando questo perché ne avevamo discusso in classe, ma non sembra funzionare.

risposta

7

Il motivo di questo comportamento è che Python ottimizza i piccoli numeri interi in modo che non si trovino effettivamente in una posizione di memoria diversa. Controllare il id di 1, sono sempre la stessa:

>>> x = 1 
>>> y = 1 
>>> id(x) 
1353557072 
>>> id(y) 
1353557072 

>>> a = [1, 2, 3, 4, 5] 
>>> id(a[0]) 
1353557072 

>>> import copy 
>>> b = copy.deepcopy(a) 
>>> id(b[0]) 
1353557072 

Riferimento da Integer Objects:

L'implementazione corrente mantiene un array di oggetti interi per tutti gli interi tra -5 e 256, quando crei un int in quell'intervallo, in realtà ottieni soltanto un riferimento all'oggetto esistente. Quindi dovrebbe essere possibile modificare il valore di 1. Sospetto che il comportamento di Python in questo caso non sia definito. :-)

+0

Non è quello che stai descrivendo il principio delle "copie superficiali", ad esempio copy.copy (a), quando si utilizza copy.deepcopy (a), gli elementi non dovrebbero essere tutti in posizioni di memoria diverse, ovvero quell'id (a [0]) ! = id (b [0]) –

+0

@GeraldLee: Questo è un caso speciale, in quanto i "piccoli" numeri interi ('<257') verranno corretti nella posizione di memoria per accelerare le operazioni comuni. Prova quanto segue: 'a, b = (lista (intervallo (258)), lista (intervallo (258))); [id (a [i]) == id (b [i]) per i in gamma (258)] 'in python REPL – Steen

+0

Gli inti piccoli sono esempi di singleton Python. Altri sono 'None',' True' e 'False' – PMende

0

La risposta di Yu Hao in realtà non è corretta. È vero che Python ha oggetti unici per interi piccoli, ma non è ciò che causa quel comportamento.

Verificare cosa succede quando si utilizzano numeri interi più grandi.

> from copy import deepcopy 
> x = 1000 
> x is deepcopy(x) 
True 

Se si scava giù nel modulo copy si scopre che quando si deepcopy un valore atomico, si rinvia la chiamata a una funzione chiamata _deepcopy_atomic.

def _deepcopy_atomic(x, memo): 
    return x 

Così che cosa sta realmente accadendo è che deepcopy non copierà un valore immutabile, ma solo restituirlo.

I tipi che sono considerati essere Atomics includono int, float, bool, str e molti altri.