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.