2013-07-02 14 views
51

Questo è il mio codice:Get: TypeError: oggetto 'dict_values' non supporta l'indicizzazione quando si usa Python 3.2.3

{names[i]:d.values()[i] for i in range(len(names))} 

Questo funziona tutto bene quando si utilizza python 2.7.3; tuttavia, quando utilizzo python 3.2.3, viene visualizzato un errore che indica 'dict_values' object does not support indexing. Come posso modificare il codice per renderlo compatibile per 3.2.3?

+1

'values' restituisce ora un oggetto di visualizzazione http://docs.python.org/3.2/library/stdtypes.html#dictionary-view-objects – dm03514

+3

Perché stai facendo affidamento sull'ordine dei' valori' restituiti da un dizionario comunque? –

+0

Sì, questo codice non è affidabile a meno che d non sia un 'OrderedDict' - e anche se è così sembra che ci debba essere un modo migliore. –

risposta

81

In Python 3, dict.values() (insieme a dict.keys() e dict.items()) restituisce un view anziché un elenco. Vedere la documentazione here. È quindi necessario per avvolgere la chiamata a dict.values() in una chiamata a list in questo modo:

v = list(d.values()) 
{names[i]:v[i] for i in range(len(names))} 
+1

@JessePet Sembra che tu abbia errato 'valori' come' vaule' lì. – andersschuller

+0

@andersshuller: eri corretto. –

+1

Il codice dell'OP è unpythonic per tutti quelli che lo guardano: in Python evitiamo gli indici (più lenti, più brutti). Il modo corretto è quello di @ DavidRobinson's [answer] (https://stackoverflow.com/a/17431678/281545): 'dict (zip (nomi, d.values ​​()))'. Ovviamente questo codice si basa anche sui valori ordinati come nomi che non sono affatto garantiti. –

6

Una versione più semplice del codice sarebbe:

dict(zip(names, d.values())) 

Se si desidera mantenere la stessa struttura, è possibile modificarla in:

vlst = list(d.values()) 
{names[i]: vlst[i] for i in range(len(names))} 

(Si può altrettanto facilmente mettere list(d.values()) all'interno della comprensione invece di vlst, è semplicemente inutile farlo poiché sarebbe rigenerare la lista ogni volta).

+0

Sfortunatamente, quando uso l'esempio di vlst, ottengo un errore "L'oggetto '' dict 'non ha attributi' valori ' –

+0

@JessePet: Non vedo come sia possibile, soprattutto dal momento che nel proprio codice' d.values ​​() 'ha funzionato senza errori (fino a quando non hai provato ad indicizzarlo).È possibile che abbiate errato 'valori' o qualche errore simliar? –

+0

Non ho sbagliato l'ortografia dei valori, mi sorprende a dir poco –

2

In Python 3 il metodo restituisce un dict.values()dictionary view object, non una lista come fa in Python 2. viste Dizionario hanno una lunghezza, può essere iterato e supportare il test di appartenenza, ma non supporta l'indicizzazione.

per rendere il lavoro di codice in entrambe le versioni, è possibile utilizzare uno questi:

{names[i]:value for i,value in enumerate(d.values())} 

        o

values = list(d.values()) 
{name:values[i] for i,name in enumerate(names)} 

Di gran lunga il modo più veloce, più semplice fare la stessa cosa in entrambe le versioni sarebbe:

dict(zip(names, d.values())) 

Si noti tuttavia che tutti questi metodi forniranno risultati che varieranno a seconda del contenuto effettivo di d. Per ovviare a questo, potresti utilizzare uno OrderedDict, che ricorda l'ordine in cui le chiavi sono state inserite per la prima volta, in modo da poter contare sull'ordine di ciò che viene restituito dal metodo values().

Problemi correlati