Zugriff auf das Element dict_keys über den Index in Python3


131

Ich versuche, über den Index auf das Element eines dict_key zuzugreifen:

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

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

Ich will bekommen foo.

Das gleiche mit:

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

Wie kann ich das machen?


9
In py3.x wird dict.keys()ein Satz wie ein Ansichtsobjekt zurückgegeben, keine Liste (eine Indizierung ist daher nicht möglich). Verwenden Siekeys = list(test)
Ashwini Chaudhary

Wenn ich liste (Something_Dict), ist die Tupelreihenfolge zufällig: Beispiel: Liste ({'foo': 'bar', 'hallo': 'Welt'}) kann zurückgeben: Liste (foo, hallo) oder Liste (hallo, foo), warum ist das zufällig?
fj123x

7
Diktate haben keine Bestellung . (Verwenden collections.OrderedDictSie, wenn Sie bestellte Schlüssel möchten)
Ashwini Chaudhary

Interessante Diskussion über Thread-Sicherheit hier erneut die verschiedenen Ansätze zur Lösung dieses Problems: blog.labix.org/2008/06/27/…
Paul

Antworten:


160

Rufen Sie list()stattdessen das Wörterbuch auf:

keys = list(test)

In Python 3 gibt die dict.keys()Methode ein Wörterbuchansichtsobjekt zurück , das als Menge fungiert. Wenn Sie das Wörterbuch direkt durchlaufen, erhalten Sie auch Schlüssel. Wenn Sie also ein Wörterbuch in eine Liste umwandeln, erhalten Sie eine Liste aller Schlüssel:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

3
Achten Sie auf die Liste (dict.keys ()) in Python 3 - Labix Blog erklärt klar, was das Problem ist, ohne eine Lösung bereitzustellen . Das ist ausgezeichnet!
Brandon Bradley

@BrandonBradley: Im Allgemeinen ist es ohnehin eine schlechte Idee, sich darauf zu verlassen, dass bestimmte Aktionen atomar sind, da Python so hochdynamisch ist. Ihr Code kann leicht an eine dictUnterklasse übergeben werden, die beispielsweise .keys()in Python-Code behandelt wird (z. B. kann ein Threadwechsel stattfinden).
Martijn Pieters

@BrandonBradley: Danke für den Link. In Python3 funktioniert nur die Lösung aus einem der Kommentare für diesen Blog: sortiert (dict.keys ()). In Python2 gibt dict.keys () eine Liste der Schlüsselwerte zurück.
Good Will

2
@ GoodWill: sorted(dict)würde genau das gleiche tun; Erstellen Sie eine Liste der Schlüssel in sortierter Reihenfolge. list(dict)gibt Ihnen die Liste in Wörterbuchreihenfolge.
Martijn Pieters

1
oder zu verwendenkeys = [*test]
Alex78191

59

Keine vollständige Antwort, aber vielleicht ein nützlicher Hinweis. Wenn es wirklich das erste Element ist, das Sie möchten *, dann

next(iter(q))

ist viel schneller als

list(q)[0]

für große dikte, da das ganze nicht im speicher gespeichert werden muss.

Für 10.000.000 Artikel war es fast 40.000 Mal schneller.

* Das erste Element, falls ein Diktat nur ein pseudozufälliges Element vor Python 3.6 ist (danach wird es in der Standardimplementierung bestellt, obwohl nicht empfohlen wird, sich darauf zu verlassen).


5
Dies war schon immer eines meiner größten Probleme, da alles in Py3 zu Iteratoren wurde. Es ist definitiv effizienter, aber so viele Anwendungsfälle werden ohne Grund "unrein" und kompliziert. Warum können sie beispielsweise nicht einfach die Indizierung auf dem Iterator unterstützen, ohne notwendigerweise einen Leistungsverlust zu haben?
Ehsan Kia

2

Ich wollte ein Paar "Schlüssel" und "Wert" eines ersten Wörterbuchelements. Ich habe den folgenden Code verwendet.

 key, val = next(iter(my_dict.items()))

0
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

Herkömmliche Methode zum Anhängen der Schlüssel an eine statisch definierte Liste und anschließendes Indizieren derselben


2
Es ist nicht falsch, aber warum nicht ls = list(test.keys())? Ich finde es einfacher.
Valentino

Ja, das ist effizienter. Ich habe dies nur geschrieben, um die Lesbarkeit zu zeigen.
Pranav Dua

0

In vielen Fällen kann dies ein XY-Problem sein . Warum indizieren Sie Ihre Wörterbuchschlüssel nach Position? Müssen Sie wirklich? Bis vor kurzem wurden Wörterbücher nicht einmal in Python bestellt, sodass der Zugriff auf das erste Element willkürlich war.

Ich habe gerade Python 2-Code in Python 3 übersetzt:

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

Das ist nicht schön, aber auch nicht sehr schlecht. Zuerst wollte ich es durch das Ungeheuerliche ersetzen

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

bevor mir klar wurde, ist das alles viel besser geschrieben als

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

das funktioniert gut.

Ich glaube, dass in vielen anderen Fällen die Indizierung von Wörterbuchschlüsseln nach Position vermieden werden kann. Obwohl Wörterbücher in Python 3.7 bestellt werden, ist es nicht schön, sich darauf zu verlassen. Der obige Code funktioniert nur, weil der Inhalt vonsome_list kürzlich aus dem Inhalt von erstellt wurde d.

Sehen Sie sich Ihren Code genau an, wenn Sie wirklich über einen disk_keysIndex auf ein Element zugreifen müssen . Vielleicht musst du nicht.


0

Versuche dies

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

Das Ergebnis sieht so aus. ['foo', 'hallo']

Weitere mögliche Lösungen finden Sie hier .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.