2012-03-15 15 views
5

Sono confuso con il riferimento a Python. Si consideri il seguente esempio:Come funziona il riferimento a Python?

Il mio compito: di modificare ogni elemento della lista

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[1:] # m changes its reference to the new sliced list, edits m but not d (I wanted to change d) 

Allo stesso modo:

d = { 'm': [1,2,3] } 
m = d['m'] 
m = m[0] # As per python referencing, m should be pointing to d['m'] and should have edited d 

in Python tutto va per riferimento, poi, quando è un nuovo oggetto creato? Abbiamo sempre bisogno di copy e deepcopy dal modulo copy per creare copie di oggetti?

Si prega di chiarire.

+1

Se sei un principiante visivo, [ecco] (http://people.csail.mit.edu/pgbovine/python /) un buon tutorial – forivall

+0

Commento estremamente utile Mr. @jordoex - Davvero impressionante! –

risposta

11

In Python una variabile non è una casella che contiene oggetti, è un nome che punta a un oggetto. Nel codice:

  • d = { 'm': [1,2,3] } -> si lega il nome d a un dizionario
  • m = d['m'] -> si lega il nome m a un elenco
  • m = m[1:] -> si lega il nome m ad un altro elenco

La terza riga non sta cambiando m stesso, ma a che cosa punta m.

Per modificare gli elementi della lista che cosa si può fare è:

m = d['m'] 
for i, item in enumerate(m): 
    result = do_something_with(item) 
    m[i] = result 
+0

Esiste un altro modo per modificare ogni elemento di questa lista oltre a "enumerare"? –

+0

"Un nome che punta a un oggetto" potrebbe confondere, poiché "pointer" non è la terminologia Python. Direi semplicemente "è un nome per un oggetto". –

+0

"La terza riga non sta cambiando m stesso, ma ciò che m sta puntando a" potrebbe essere un po 'poco chiaro per il lettore. Per essere più espliciti: "la terza riga cambia m dal puntare a una cosa (d ['m']) per indicare un'altra cosa ([2,3])." –

5

Ethan Furman ha fatto un ottimo lavoro di spiegare come Python interni lavoro, non mi ripeto.

Poiché m rappresenta realmente l'elenco all'interno del dizionario, è possibile modificarlo. Non è possibile riassegnarlo a qualcosa di nuovo, che è ciò che accade quando si utilizza = per equipararlo a una nuova sezione.

per tagliare fuori il primo elemento della lista, ad esempio:

>>> m[0:1] = [] 
>>> d 
{'m': [2, 3]} 
+4

Odio guidare da downvotes, se ho fatto qualcosa di sbagliato mi piace scoprire perché. Questa risposta è stata testata in Python 2.7 usando un idioma consigliato: http://docs.python.org/library/stdtypes.html#mutable-sequence-types –

+0

Penso che sia una buona intuizione Mark, e non so perché è stato downvoted ... –

+2

Per eliminare elementi o sezioni da un elenco di solito preferisco il più esplicito 'del m [0]'. Naturalmente questa è una preferenza stilistica, e non ho idea del motivo per cui qualcuno ha votato a bassa quota. La mia ipotesi è che molti di quei downvotes apparentemente casuali derivano da display troppo piccoli di smartphone. –

4

in Python tutto va facendo riferimento

In Python, tutto è un punto di riferimento, ed i riferimenti essere passati in giro per valore.

Se si desidera utilizzare questi termini. Ma quei termini rendono le cose più difficili da capire.

Molto più semplice: in Python, una variabile è un nome per un oggetto. = viene utilizzato per modificare l'oggetto a cui si riferisce un nome. Il lato sinistro può fare riferimento a parte di un oggetto esistente, nel qual caso l'intero oggetto viene modificato sostituendo quella parte. Questo perché l'oggetto, a sua volta, non contiene realmente le sue parti, ma contiene invece più nomi, che possono essere causati per iniziare a riferirsi a cose diverse.

quindi quando viene creato un nuovo oggetto?

Gli oggetti vengono creati quando vengono creati (utilizzando il costruttore di classi o, nel caso di tipi built-in che hanno una rappresentazione letterale, digitando un valore letterale). Non capisco come questo sia rilevante per il resto della tua domanda.

m = m[1:] # m changes its reference to the new sliced list 

Sì, certo. Ora m si riferisce al risultato della valutazione di m[1:].

edits m but not d (I wanted to change d) 

Sì, certo. Perché cambia d? Non era una specie di magia, era semplicemente il risultato della valutazione di d['m']. Esattamente la stessa cosa accade su entrambe le linee.

Diamo un'occhiata ad un esempio più semplice.

m = 1 
m = 2 

Questo causa 1 per diventare 2? No certo che no. I numeri interi sono immutabili. Ma la stessa cosa sta succedendo: m è causato da un nome a una cosa, e poi a un altro nome.

Oppure, in un altro modo: se i "riferimenti" dovessero funzionare come previsto, la linea m = m[1:] sarebbe ricorsiva. Ti aspetti che significhi "ovunque tu veda m, trattalo come se significasse m[1:]". Beh, in questo caso, m[1:] sarebbe in realtà significherebbe m[1:][1:], che sarebbe poi significherebbe m[1:][1:][1:], ecc