182 votes

Accès à l'élément dict_keys par index en Python3

J'essaie d'accéder à l'élément d'un dict_key par son index :

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

Je veux obtenir foo .

même avec :

keys[0]
TypeError: 'dict_keys' object does not support indexing

Comment puis-je le faire ?

0voto

gerrit Points 1588

Dans de nombreux cas, il peut s'agir d'un Problème XY . Pourquoi indexez-vous les clés de votre dictionnaire par position ? En avez-vous vraiment besoin ? Jusqu'à récemment, les dictionnaires n'étaient même pas ordonnés en Python, et l'accès au premier élément était donc arbitraire.

Je viens de traduire du code Python 2 en Python 3 :

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

ce qui n'est pas joli, mais pas très mauvais non plus. Au départ, j'étais sur le point de le remplacer par le monstrueux

    k = next(itertools.islice(iter(keys), i, None))

avant que je ne réalise que tout ceci est bien mieux écrit sous la forme de

for (k, res) in zip(d.keys(), some_list):

ce qui fonctionne très bien.

Je pense que dans de nombreux autres cas, l'indexation des clés de dictionnaire par position peut être évitée. Bien que les dictionnaires soient ordonnés dans Python 3.7, se fier à cela n'est pas très joli. Le code ci-dessus ne fonctionne que parce que le contenu de some_list avait été récemment produit à partir du contenu de d .

Examinez attentivement votre code si vous avez réellement besoin d'accéder à un fichier disk_keys élément par indice. Peut-être n'en avez-vous pas besoin.

0voto

not a robot Points 1674

Si vous avez besoin de découper les clés du dictionnaire (pas seulement la première clé), au lieu d'appeler list() sur test , généraliser la méthode dans La réponse de Mark en utilisant islice à partir de l'outil intégré itertools module.

from itertools import islice
# slice test.keys from index l to index u
some_keys = list(islice(test, l, u))

En fonction de la taille de la tranche par rapport à la taille du dictionnaire, cette méthode est de 50% à >40000x plus rapide que

list(test)[l:u]

Par exemple, dans l'exemple ci-dessous, il est >43000x plus rapide.

n = 10_000_000
test = dict(zip(range(n), [0,1,2,3,4]*(n//5)))

%timeit list(islice(test, 10, 30))
# 4.43 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(test)[10:30]
# 192 ms ± 2.65 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X