2010-07-04 14 views
25

Sto provando a modificare gli elementi in un elenco utilizzando un ciclo for, ma ottengo un errore (vedi sotto). Esempio di codice:Modifica delle voci dell'elenco nel loop (python)

#!/usr/bin/env python 
# *-* coding: utf8 *-* 

data = [] 
data.append("some") 
data.append("example") 
data.append("data") 
data.append("here") 

for item in data: 
    data[item] = "everything" 

Errore:

Traceback (most recent call last): 
    File "./testy.py", line 11, in <module> 
    data[item] = "everything" 
TypeError: list indices must be integers, not str 

C'è un modo per risolvere questo problema?

risposta

57

Prova a modificare:

for i in xrange(len(data)): 
    data[i] = "everything" 

Il problema di fondo che stai avendo è che quando si scrive data[i], con data essendo un elenco, le i deve essere un numero intero, un indice numerico nella lista. Ma nel ciclo

for item in data 

item è la cosa reale che è nella lista, vale a dire una stringa, non l'indice numerico della cosa. xrange è un iteratore che produce numeri anziché i valori nell'elenco, quindi è possibile utilizzarlo.

Un'alternativa sarebbe

for i, _ in enumerate(data): 
    data[i] = "everything" 

La funzione enumerate ti dà un iteratore su tuple nella forma (index, item), quindi tutto quello che dovete fare è prendere l'indice e dimenticare la voce. Non sono sicuro che in un modo o nell'altro (enumerate o xrange) sarà significativamente più veloce o migliore, poiché penso che le liste memorizzino la loro lunghezza in una variabile in modo che possa essere rapidamente accessibile senza contare gli elementi dell'elenco.

Tuttavia, se è necessario il valore della lista vecchia per calcolare il nuovo valore della lista, il modo in cui enumerate sarà probabilmente un po 'più veloce perché si evita di fare Python cercare l'elemento della lista:

for i, item in enumerate(data): 
    data[i] = func(item) 

Questo tipo di cosa è meglio espresso in comprensione lista, però:

data = [func(item) for item in data] 

Quando si esegue questa operazione, Python passare attraverso ogni elemento in data, applicare la funzione ad essa, e costruire un nuovo elenco dai risultati automaticamente, in modo da y Non devi preoccuparti di inserire il risultato di func(item) nel posto giusto nell'elenco. Il tuo esempio originale potrebbe in realtà essere espressa come

data = ["everything" for item in data] 
+0

Sembra un po 'strano (o soluzione), ma funziona in modo corretto. Non sapevo che gli elementi prioritari (nella lista) devono avere il loro ID. Grazie. –

+4

@sigo: che in realtà non è affatto una soluzione, è il modo corretto e perfettamente normale al 100% di eseguire questo tipo di attività (ma si noti ciò che ho detto sulla comprensione delle liste). –

+2

In questo caso particolare, la comprensione delle liste potrebbe essere sostituita dal più veloce 'data = [" tutto "] * len (dati)'. – EOL

5

elementi dell'elenco sono accessibili indice intero, i. e. nell'esempio data[1] == 'example'. Questo è il motivo per cui Python si lamenta quando stai usando una stringa come ricerca.

Se si vuole trovare un elemento in un elenco per il suo valore, è possibile utilizzare data.index("value"):

data[data.index("some")] = "something else" 

Ma se si desidera solo per un ciclo su di loro, utilizzare enumerate() come David suggerito.

0

l'indicizzazione di un elenco utilizzando numeri interi potrebbe essere inefficiente. È probabile che Python memorizzi gli elementi in elenco usando la tabella collegata con puntatori sottostanti.In questo caso, per trovare un oggetto specifico, python deve attraversare l'elenco fino all'elemento i-esimo.

Si suggerisce che utilizzando il formato come questo potrebbe essere efficiente: un [:] = [x * x per x in una]