2012-01-07 7 views
5

Ho passato le ultime 2 ore a questo e probabilmente ho letto tutte le domande qui relative alle variabili passate alle funzioni. Il mio problema è quello comune del parametro/argomento influenzato dalle modifiche apportate all'interno della funzione, anche se ho rimosso il riferimento/alias utilizzando variable_cloned = variable[:] nella funzione per copiare i contenuti senza il riferimento.L'argomento/parametro passato nella funzione è ancora in fase di modifica dopo aver rimosso il riferimento/alias

Ecco il codice:

def add_column(m):  
    #this should "clone" m without passing any reference on  
    m_cloned = m[:] 
    for index, element in enumerate(m_cloned): 
     # parameter m can be seen changing along with m_cloned even 
     # though 'm' is not touched during this function except to 
     # pass it's contents onto 'm_cloned'   
     print "This is parameter 'm' during the for loop...", m 
     m_cloned[index] += [0] 
    print "This is parameter 'm' at end of for loop...", m  
    print "This is variable 'm_cloned' at end of for loop...", m_cloned 
    print "m_cloned is m =", m_cloned is m, "implies there is no reference" 
    return m_cloned 

matrix = [[3, 2], [5, 1], [4, 7]] 
print "\n" 
print "Variable 'matrix' before function:", matrix 
print "\n" 
add_column(matrix) 
print "\n" 
print "Variable 'matrix' after function:", matrix 

Quello che sto notando è che il parametro 'm' nella funzione sta cambiando, come se è un alias di m_cloned - ma per quanto mi riguarda posso dire che ho rimosso l'alias con la prima riga della funzione. Ovunque ho guardato online sembra suggerire che questa linea si assicurerà che non ci sia alcun riferimento ai parametri, ma non funziona.

Sono sicuro di aver fatto un semplice errore ma dopo 2 ore non penso di trovarlo.

+1

"... anche se ho rimosso il riferimento/alias usando variable_cloned = variabile [:] nella funzione per copiare i contenuti senza il riferimento. " Ciò rende 'variable_cloned' fare riferimento a una lista separata da' variable', ma i due elenchi conterranno contenuti identici: riferimenti ai tuoi tre (2-item) elenchi. –

risposta

9

Sembra che tu abbia bisogno di un deepcopy, invece di una copia, che è quello che [:] ti dà:

from copy import deepcopy 
list2 = deepcopy(list1) 

Ecco un esempio più confronto tra i due tipi di copia:

from copy import deepcopy 

list1 = [[1], [1]] 
list2 = list1[:] # while id(list1) != id(list2), it's items have the same id()s 
list3 = deepcopy(list1) 

list1[0] += [3] 

print list1 
print list2 
print list3 

Uscite:

[[1, 3], [1]] # list1 
[[1, 3], [1]] # list2 
[[1], [1]]  # list3 - unaffected by reference-madness 
+0

Wow grazie, non ci sarei mai arrivato da solo. Sto guardando [link] (http://docs.python.org/library/copy.html) che sembra in qualche modo spiegare le differenze tra copia profonda e superficiale, ma non sono sicuro di cosa significhi praticamente - dovrei fare deepcopy ogni volta che passo una variabile a una funzione? – FiveAlive

+1

@FiveAlive Non necessariamente. A volte vuoi mantenere i riferimenti ad oggetti "figli". A volte non importa (quando si tratta di "bambini" immutabili), dal momento che cose come stringhe/intarsi non possono cambiare i valori, ma sono sostituite da nuove copie, il che non sarebbe un problema nel tuo caso. "Conoscere" è metà della battaglia (dicono), ora che lo sai, sono sicuro che presterai maggiore attenzione la prossima volta a ciò di cui hai bisogno. –

+0

Grazie ancora, questo ha chiarito tutto per me :) – FiveAlive

Problemi correlati