Come restituire le chiavi del dizionario come elenco in Python?


784

In Python 2.7 , potrei ottenere chiavi del dizionario , valori o elementi come un elenco:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

Ora, in Python> = 3.3 , ottengo qualcosa del genere:

>>> newdict.keys()
dict_keys([1, 2, 3])

Quindi, devo farlo per ottenere un elenco:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

Mi chiedo, c'è un modo migliore per restituire un elenco in Python 3 ?


L'interessante problema di sicurezza dei thread relativo a questo argomento è qui: blog.labix.org/2008/06/27/…
Paul,

2
Sono nuovo di Python, e per me sembra che questa proliferazione di nuovi tipi di dati inutili sia uno degli aspetti peggiori di Python. A che serve questo tipo di dati dict_keys? Perché non un elenco?
Phil Goetz,

Risposte:


978

Prova list(newdict.keys()).

Questo convertirà l' dict_keysoggetto in un elenco.

D'altra parte, dovresti chiederti se è importante o meno. Il modo Pythonic di codificare è quello di assumere la digitazione di anatra ( se sembra un'anatra e cade come un'anatra, è un'anatra ). L' dict_keysoggetto funzionerà come un elenco per la maggior parte degli scopi. Per esempio:

for key in newdict.keys():
  print(key)

Ovviamente, gli operatori di inserimento potrebbero non funzionare, ma ciò non ha comunque molto senso per un elenco di chiavi del dizionario.


49
newdict.keys () non supporta l'indicizzazione
gypaetus,

57
list(newdict)funziona anche (almeno in Python 3.4). C'è qualche motivo per usare il .keys()metodo?
naught101

46
Nota: nel debugger pdb> list(newdict.keys()) fallisce perché si scontra con il comando pdb con lo stesso nome. Utilizzare pdb> !list(newdict.keys())per sfuggire ai comandi pdb.
Riaz Rizvi,

24
@ naught101 Sì, .keys()è molto più chiaro su ciò che accade.
Felix D.

2
Nota che se usi list (newdict.keys ()) che le chiavi non sono nell'ordine in cui le hai inserite a causa di un ordine di hashing!
Nate M,

278

Python> = 3.5 alternativa: decomprimere in un elenco letterale [*newdict]

Sono state introdotte nuove generalizzazioni di decompressione (PEP 448) con Python 3.5 che consente ora di eseguire facilmente:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

Disimballare con *funziona con qualsiasi oggetto iterabile e, poiché i dizionari restituiscono le loro chiavi quando vengono iterati, è possibile creare facilmente un elenco utilizzandolo all'interno di un elenco letterale.

L'aggiunta, ad .keys()esempio, [*newdict.keys()]potrebbe aiutare a rendere un po 'più esplicito il tuo intento, anche se ti costerà una funzione di ricerca e invocazione. (che, in tutta onestà, non è qualcosa di cui dovresti davvero preoccuparti).

La *iterablesintassi è simile al fare list(iterable)e il suo comportamento è stato inizialmente documentato nella sezione Chiamate del manuale di riferimento di Python. Con PEP 448 la restrizione su dove *iterablepotrebbe apparire è stata allentata permettendo di posizionarla anche in elenco, impostare e tuple letterali, il manuale di riferimento sugli elenchi di espressioni è stato aggiornato per affermarlo.


Sebbene equivalente a list(newdict)con la differenza che è più veloce (almeno per i dizionari di piccole dimensioni) perché in realtà non viene eseguita alcuna chiamata di funzione:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

con dizionari più grandi la velocità è praticamente la stessa (il sovraccarico di iterare attraverso una grande raccolta supera il piccolo costo di una chiamata di funzione).


In modo simile, puoi creare tuple e set di chiavi del dizionario:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

attenzione alla virgola finale nel caso tupla!


grande spiegazione, ma per favore puoi fare riferimento a qualsiasi link che descriva questo tipo di sintassi "* newdict", intendo come e perché questo ritorni le chiavi dal dizionario solo per capire
Grazie

1
@MYounas Quella sintassi è disponibile da un po 'di tempo, anche in Python 2. Nelle chiamate di funzione è possibile fare def foo(*args): print(args)seguito dal foo(*{1:0, 2:0})risultato in (1, 2)fase di stampa. Questo comportamento è specificato nella sezione Chiamate del manuale di riferimento. Python 3.5 con PEP 448 ha appena allentato le restrizioni su dove questi possono apparire consentendo [*{1:0, 2:0}]ora di essere utilizzati. Ad ogni modo, modificherò la mia risposta e includerò questi.
Dimitris Fasarakis Hilliard

1
*newdict- questa è sicuramente la risposta per i golfisti di codice; P. Inoltre: che, in tutta onestà, non è qualcosa di cui dovresti davvero preoccuparti - e se lo sei, non usare Python .
Artemis non si fida ancora del

46

list(newdict)funziona in Python 2 e Python 3, fornendo un semplice elenco delle chiavi in newdict. keys()non è necessario. (:


26

Un po 'fuori dalla definizione "typing anatra" - dict.keys()restituisce un oggetto iterabile, non un oggetto simile a un elenco. Funzionerà ovunque funzionerà un iterabile, non in nessun posto in cui un elenco funzionerà. un elenco è anche un iterabile, ma un iterabile NON è un elenco (o sequenza ...)

In casi d'uso reali, la cosa più comune da fare con i tasti in un dict è di scorrere attraverso di essi, quindi ha senso. E se ne hai bisogno come elenco, puoi chiamare list().

In modo molto simile per zip()- nella stragrande maggioranza dei casi, viene ripetuto - perché creare un intero nuovo elenco di tuple solo per iterarlo e poi buttarlo via di nuovo?

Questo fa parte di una grande tendenza in Python a utilizzare più iteratori (e generatori), piuttosto che copie di elenchi ovunque.

dict.keys() dovrebbe funzionare con comprensioni, però - controlla attentamente per errori di battitura o qualcosa del genere ... funziona bene per me:

>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]

2
Non hai nemmeno bisogno di usare .keys(); l'oggetto dizionario è in sé iterabile e produce tasti quando iterata: [key.split(", ") for key in d].
Martijn Pieters

25

Puoi anche utilizzare una comprensione dell'elenco :

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

O, più breve,

>>> [k  for  k in  newdict]
[1, 2, 3]

Nota: l'ordine non è garantito nelle versioni sotto 3.7 (l'ordinamento è ancora solo un dettaglio di implementazione con CPython 3.6).


6
Basta usare list(newdict). Non è necessario per la comprensione di un elenco qui.
Martijn Pieters

8

La conversione in un elenco senza utilizzare il keysmetodo lo rende più leggibile:

list(newdict)

e, quando si esegue il ciclo tra i dizionari, non è necessario keys():

for key in newdict:
    print key

a meno che non lo si modifichi all'interno del ciclo che richiederebbe un elenco di chiavi create in precedenza:

for key in list(newdict):
    del newdict[key]

Su Python 2 c'è un guadagno di performance marginale usandokeys() .


8

Se è necessario archiviare le chiavi separatamente, ecco una soluzione che richiede meno digitazione rispetto a qualsiasi altra soluzione presentata finora, utilizzando Extended Iterable Unpacking (python3.x +).

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
             k = list(d)      9 characters (excluding whitespace)   
            ├───────────────┼─────────────────────────────────────────┤
             k = [*d]         6 characters                          
            ├───────────────┼─────────────────────────────────────────┤
             *k, = d          5 characters                          
            ╘═══════════════╧═════════════════════════════════════════╛

1
L'unico avvertimento minore che vorrei sottolineare è che kè sempre un elenco qui. Se un utente desidera una tupla o un set dai tasti dovrà ricorrere alle altre opzioni.
Dimitris Fasarakis Hilliard,

1
Una nota più degna di nota è il fatto che, come affermazione, *k, = dha dei limiti su dove può apparire (ma vedi, e forse aggiorna questa risposta per, PEP 572 - il disimballaggio esteso non è supportato per le espressioni di assegnazione ATM, ma potrebbe essere un giorno! )
Dimitris Fasarakis Hilliard,

cosa succede se si desidera che sia le chiavi che i valori vengano elencati?
endolith,

1
@endolith forse keys, vals = zip(*d.items())(anche se questo dà due tuple, abbastanza vicino). Non conosco un'espressione più breve di questa.
cs95,

1

Posso pensare a 2 modi in cui possiamo estrarre le chiavi dal dizionario.

Metodo 1: - Per ottenere le chiavi utilizzando il metodo .keys () e convertirlo in elenco.

some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]

Metodo 2: - Per creare un elenco vuoto e quindi aggiungere le chiavi all'elenco tramite un ciclo. Puoi ottenere anche i valori con questo ciclo (usa .keys () solo per le chiavi e .items () sia per l'estrazione delle chiavi che dei valori)

list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
    list_of_keys.append(key)
    list_of_values.append(val)

print(list_of_keys)
-->[1,2,3]

print(list_of_values)
-->['one','two','three']
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.