Comment retourner les clés du dictionnaire sous forme de liste en Python?

Dans Python 2.7, j'ai pu obtenir dictionnaire clés, les valeurs de, ou d'éléments de, comme une liste:

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

Maintenant, Python >= 3.3, j'obtiens quelque chose comme ceci:

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

Donc, je dois le faire pour obtenir une liste:

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

Je me demande s'il existe une meilleure façon de renvoyer une liste dans Python 3?

341
demandé sur Jim Fasarakis Hilliard 2013-05-29 20:24:16

9 réponses

Essayez list(newdict.keys()).

Cela convertira l'objet dict_keys en une liste.

D'autre part, vous devriez vous demander si c'est important ou non. La façon pythonique de coder est de supposer le typage duck ( si cela ressemble à un canard et qu'il charlate comme un canard, c'est un canard). L'objet dict_keys agira comme une liste dans la plupart des cas. Par exemple:

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

Évidemment, les opérateurs d'insertion peuvent ne pas fonctionner, mais cela n'a pas beaucoup de sens pour une liste de clés de dictionnaire de toute façon.

427
répondu Chris 2017-10-11 15:46:05

Python > = 3.5 alternative: décompresser dans un littéral de liste [*newdict]

De nouvelles généralisations de déballage (pep 448) {[17] } ont été introduites avec Python 3.5 vous permettant de faire maintenant facilement:

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

Le déballage avec *fonctionne avec tout objet itérable et, puisque les dictionnaires retournent leurs clés lorsqu'ils sont itérés, vous pouvez facilement créer une liste en l'utilisant dans un littéral de liste.

Ajouter .keys() c'est-à-dire {[6] } pourrait aider à faire votre intention un peu plus explicite si cela vous coûtera une recherche de fonction et une invocation. (qui, en toute honnêteté, n'est pas quelque chose que vous devriez vraiment être inquiet).

La syntaxe *iterable est similaire à doing list(iterable) et son comportement a été initialement documenté dans la section Calls du manuel de référence Python. Avec PEP 448, la restriction sur l'endroit où *iterable pouvait apparaître a été assouplie, ce qui lui a permis d'être également placé dans les littéraux list, set et tuple, le manuel de référence sur listes D'expressions a également été mis à jour pour l'indiquer.


Bien qu'équivalent à list(newdict) à la différence qu'il est plus rapide (au moins pour les petits dictionnaires) car aucun appel de fonction n'est réellement effectué:

%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

Avec les dictionnaires plus grands, la vitesse est à peu près la même (la surcharge d'itérer à travers une grande collection l'emporte sur le faible coût d'un appel de fonction).


De la même manière, vous pouvez créer des tuples et des ensembles de dictionnaire touches:

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

Méfiez-vous de la virgule finale dans le cas du tuple!

88
répondu Jim Fasarakis Hilliard 2018-04-07 11:20:44

Un peu hors de la définition "Duck typing" -- dict.keys() renvoie un objet itérable, pas un objet de type liste. Cela fonctionnera partout où un itérable fonctionnera - pas n'importe quel endroit une liste le fera. une liste est également un itérable, mais un itérable N'est pas une liste (ou une séquence...)

Dans les cas d'utilisation réels, la chose la plus courante à faire avec les clés dans un dict est de les parcourir, donc cela a du sens. Et si vous en avez besoin comme une liste, vous pouvez appeler list().

Très similaire pour zip() -- dans le vaste la majorité des cas, il est itéré-pourquoi créer une nouvelle liste entière de tuples juste pour itérer à travers elle et ensuite la jeter à nouveau?

Cela fait partie d'une grande tendance en python à utiliser plus d'itérateurs (et de générateurs), plutôt que des copies de listes partout.

dict.keys() devrait fonctionner avec des compréhensions, cependant-vérifiez soigneusement les fautes de frappe ou quelque chose... il fonctionne très bien pour moi:

>>> 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']]
21
répondu Chris Barker 2015-03-04 23:58:05

list(newdict) fonctionne à la fois dans Python 2 et Python 3, fournissant une liste simple des clés dans newdict. keys() n'est pas nécessaire. (:

18
répondu Seb 2018-04-18 18:40:43

Vous pouvez également utiliser une Liste compréhension :

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]
7
répondu jack yang 2017-07-22 10:58:30

La conversion en liste sans utiliser la méthode keys la rend plus lisible:

list(newdict)

Et, en boucle dans les dictionnaires, il n'y a pas besoin de keys():

for key in newdict:
    print key

Sauf si vous le modifiez dans la boucle, ce qui nécessiterait une liste de clés créées à l'avance:

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

sur Python 2 Il y a un gain de performance marginal en utilisant keys().

5
répondu Cas 2017-10-11 15:45:09

Autres que les moyens mentionnés sur cette page, vous pouvez utiliser itemgetter à partir du module opérateur:

>>> from operator import itemgetter
>>> list(map(itemgetter(0), dd.items()))
[1, 2, 3]
2
répondu Vikram S 2017-07-22 10:58:07

Vous pouvez aussi faire un tuple(dict) ou set(dict):

>>> list(set(newdict))
[1, 2, 3]
>>> list(tuple(newdict))
[1, 2, 3]
1
répondu Vikram S 2017-07-22 10:57:44

En outre, la compréhension de la liste ne semble pas fonctionner:

>>> parsed_results.keys()
dict_keys(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'])
>>> things2plot = [key.split(', ') for key in parsed_results.keys()]
>>> things2plot
['Sounder V Depth', 'F']
>>> for key in parsed_results.keys():
...     print(key.split(', '))
...     
['Sounder V Depth', 'F']
['Vessel Latitude', 'Degrees-Minutes']

Personnellement, je considère cela comme une "violation" du typage de canard, et par conséquent, un " bug."Mais je suppose que quelqu'un d'autre doit avoir remarqué cela maintenant et donc si cela n'a pas été corrigé, doit être considéré comme une "caractéristique", mais je ne peux pas pour la vie de moi voir pourquoi.

Additif en réponse à Chris:

OK, Chris, Eh bien au moins une meilleure détection et notification d'abus ("vous ne semblez pas vouloir un itérateur ici; étiez-vous attend une liste? Essayez la liste (dict.touches())...") serait plus comme le python utile que j'ai appris à connaître et à aimer. : / (Je vous demanderais des données pour sauvegarder votre affirmation selon laquelle la fonctionnalité de l'itérateur est le cas d'utilisation "le plus commun" pour dict.clés, mais vous seriez probablement en mesure de le fournir.);- ) Dans la mesure où mon exemple de compréhension de liste ne fonctionne pas (pour moi), il a été coupé-collé à partir de la ligne de commande du débogueur PyCharm, alors peut-être que le problème est un bug. (J'ai déjà rencontré un autre " bug " dans ce aujourd'hui, ça ne me surprendrait pas du tout.) Merci!

-4
répondu David Goldsmith - NOAA Affilia 2015-03-05 00:21:55