Iterieren über Wörterbücher mit 'for'-Schleifen

3138

Der folgende Code verwirrt mich ein wenig:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print key, 'corresponds to', d[key]

Was ich nicht verstehe, ist die keyPortion. Woran erkennt Python, dass nur der Schlüssel aus dem Wörterbuch gelesen werden muss? Ist keyein spezielles Wort in Python? Oder ist es einfach eine Variable?

Spitzenkoch
quelle
3
Bevor Sie eine neue Antwort veröffentlichen, sollten Sie berücksichtigen, dass diese Frage bereits über 10 Antworten enthält. Stellen Sie sicher, dass Ihre Antwort Informationen enthält, die nicht zu den vorhandenen Antworten gehören.
Janniks

Antworten:

5393

key ist nur ein Variablenname.

for key in d:

wird einfach die Schlüssel im Wörterbuch durchlaufen und nicht die Schlüssel und Werte. Um sowohl den Schlüssel als auch den Wert zu durchlaufen, können Sie Folgendes verwenden:

Für Python 3.x:

for key, value in d.items():

Für Python 2.x:

for key, value in d.iteritems():

Ändern Sie das Wort keyin, um es selbst zu testen poop.

In Python 3.x iteritems()wurde durch simply ersetzt items(), was eine satzartige Ansicht zurückgibt, die vom Diktat unterstützt wird, wie, iteritems()aber noch besser. Dies ist auch in 2.7 als verfügbar viewitems().

Die Operation items()funktioniert sowohl für 2 als auch für 3, aber in 2 wird eine Liste der Wörterbuchpaare zurückgegeben (key, value), die keine Änderungen am Diktat widerspiegelt, die nach dem items()Aufruf auftreten. Wenn Sie das 2.x-Verhalten in 3.x möchten, können Sie anrufen list(d.items()).

sberry
quelle
158
Hinzufügen eines übersehenen Grundes, nicht auf einen Wert wie diesen zuzugreifen: d [Schlüssel] in der for-Schleife bewirkt, dass der Schlüssel erneut gehasht wird (um den Wert zu erhalten). Wenn das Wörterbuch groß ist, erhöht dieser zusätzliche Hash die Gesamtzeit. Dies wird in Raymond Hettingers Tech Talk youtube.com/watch?v=anrOzOapJ2E
quiet_penguin
27
Es könnte sinnvoll sein zu erwähnen, dass Elemente in unvorhersehbarer Reihenfolge wiederholt werden und sortedzur Stabilisierung erforderlich sind.
yugr
5
@HarisankarKrishnaSwamy was ist die Alternative?
JoeyC
3
@yugr Warum sagst du das? Die Dokumentation sagt Keys and values are iterated over in insertion order. [ docs.python.org/3/library/…
Geza Turi
4
@yugr Ab Python 3.7 werden Wörterbücher nach Einfügungsreihenfolge sortiert. Dies ist eine Sprachfunktion. Siehe stackoverflow.com/a/39980744/9428564
Aimery
433

Es ist nicht so, dass der Schlüssel ein spezielles Wort ist, sondern dass Wörterbücher das Iteratorprotokoll implementieren. Sie können dies in Ihrer Klasse tun. In dieser Frage erfahren Sie beispielsweise, wie Sie Klasseniteratoren erstellen.

Bei Wörterbüchern wird es auf C-Ebene implementiert. Die Details sind in PEP 234 verfügbar . Insbesondere der Abschnitt mit dem Titel "Dictionary Iterators":

  • Wörterbücher implementieren einen tp_iter-Slot, der einen effizienten Iterator zurückgibt, der über die Schlüssel des Wörterbuchs iteriert. [...] Das heißt, wir können schreiben

    for k in dict: ...

    das ist äquivalent zu, aber viel schneller als

    for k in dict.keys(): ...

    solange die Einschränkung der Änderungen am Wörterbuch (entweder durch die Schleife oder durch einen anderen Thread) nicht verletzt wird.

  • Fügen Sie Wörterbüchern Methoden hinzu, die explizit verschiedene Arten von Iteratoren zurückgeben:

    for key in dict.iterkeys(): ...
    
    for value in dict.itervalues(): ...
    
    for key, value in dict.iteritems(): ...
    

    Dies bedeutet, dass dies for x in dicteine Abkürzung für ist for x in dict.iterkeys().

In Python 3 dict.iterkeys(), dict.itervalues()und dict.iteritems()werden nicht mehr unterstützt. Verwendung dict.keys(), dict.values()und dict.items()stattdessen.

ars
quelle
207

Das Iterieren über einen dictIter durchläuft seine Schlüssel in keiner bestimmten Reihenfolge, wie Sie hier sehen können:

Bearbeiten: (Dies ist in Python3.6 nicht mehr der Fall , aber beachten Sie, dass das Verhalten noch nicht garantiert ist. )

>>> d = {'x': 1, 'y': 2, 'z': 3} 
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']

Für Ihr Beispiel ist es besser, Folgendes zu verwenden dict.items():

>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]

Dies gibt Ihnen eine Liste von Tupeln. Wenn Sie eine Schleife über sie wie diese, ist jedes Tupel entpackt in kund vautomatisch:

for k,v in d.items():
    print(k, 'corresponds to', v)

Die Verwendung von kund vals Variablennamen beim Durchlaufen von a dictist durchaus üblich, wenn der Hauptteil der Schleife nur wenige Zeilen umfasst. Für kompliziertere Schleifen kann es eine gute Idee sein, aussagekräftigere Namen zu verwenden:

for letter, number in d.items():
    print(letter, 'corresponds to', number)

Es ist eine gute Idee, sich daran zu gewöhnen, Formatzeichenfolgen zu verwenden:

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))
John La Rooy
quelle
11
Aus den Versionshinweisen zu Python 3.7: "Die Beibehaltung der Einfügungsreihenfolge von diktierten Objekten ist jetzt ein offizieller Bestandteil der Python-Sprachspezifikation."
Gregory Arenius
86

key ist einfach eine Variable.

Für Python2.X :

d = {'x': 1, 'y': 2, 'z': 3} 
for my_var in d:
    print my_var, 'corresponds to', d[my_var]

... oder besser,

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.iteritems():
    print the_key, 'corresponds to', the_value

Für Python3.X :

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)
ssoler
quelle
63

Wenn Sie Wörterbücher mit der for .. in ..-syntax durchlaufen, werden immer die Schlüssel durchlaufen (auf die Werte kann mit zugegriffen werden dictionary[key]).

Um über Schlüssel-Wert-Paare zu iterieren, verwenden Sie in Python 2 for k,v in s.iteritems()und in Python 3 for k,v in s.items().

Alexander Gessler
quelle
38
Beachten Sie, dass es für Python 3 items()anstelle voniteritems()
Andreas Fester
19

Iterieren über Wörterbücher mit 'for'-Schleifen

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

Woran erkennt Python, dass nur der Schlüssel aus dem Wörterbuch gelesen werden muss? Ist Schlüssel ein spezielles Wort in Python? Oder ist es einfach eine Variable?

Es sind nicht nur forSchleifen. Das wichtige Wort hier ist "iterieren".

Ein Wörterbuch ist eine Zuordnung von Schlüsseln zu Werten:

d = {'x': 1, 'y': 2, 'z': 3} 

Jedes Mal, wenn wir darüber iterieren, iterieren wir über die Schlüssel. Der Variablenname keysoll nur beschreibend sein - und er ist für diesen Zweck durchaus geeignet.

Dies geschieht in einem Listenverständnis:

>>> [k for k in d]
['x', 'y', 'z']

Es passiert, wenn wir das Wörterbuch an list (oder ein anderes Objekt vom Typ Collection) übergeben:

>>> list(d)
['x', 'y', 'z']

Python iteriert in einem Kontext, in dem es erforderlich ist, die __iter__Methode des Objekts (in diesem Fall das Wörterbuch), das einen Iterator (in diesem Fall ein Keyiterator-Objekt) zurückgibt:

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

Wir sollten diese speziellen Methoden nicht selbst verwenden, sondern die entsprechende integrierte Funktion verwenden, um sie aufzurufen iter:

>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>

Iteratoren haben eine __next__Methode - aber wir nennen sie mit der eingebauten Funktion next:

>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Wenn ein Iterator erschöpft ist, wird er ausgelöst StopIteration. Auf diese Weise kann Python eine forSchleife, ein Listenverständnis, einen Generatorausdruck oder einen anderen iterativen Kontext verlassen. Sobald ein Iterator ausgelöst wird StopIteration, wird er immer ausgelöst. Wenn Sie erneut iterieren möchten, benötigen Sie einen neuen.

>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']

Zurück zu den Diktaten

Wir haben gesehen, wie Diktate in vielen Zusammenhängen iterierten. Was wir gesehen haben, ist, dass wir jedes Mal, wenn wir über ein Diktat iterieren, die Schlüssel erhalten. Zurück zum ursprünglichen Beispiel:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:

Wenn wir den Variablennamen ändern, erhalten wir immer noch die Schlüssel. Lass es uns versuchen:

>>> for each_key in d:
...     print(each_key, '=>', d[each_key])
... 
x => 1
y => 2
z => 3

Wenn wir über die Werte iterieren möchten, müssen wir die .valuesMethode der Diktate oder für beide zusammen verwenden .items:

>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]

In dem angegebenen Beispiel wäre es effizienter, die folgenden Elemente zu durchlaufen:

for a_key, corresponding_value in d.items():
    print(a_key, corresponding_value)

Aber für akademische Zwecke ist das Beispiel der Frage in Ordnung.

Aaron Hall
quelle
17

Ich habe einen Anwendungsfall, in dem ich das Diktat durchlaufen muss, um das Schlüssel-Wert-Paar sowie den Index zu erhalten, der angibt, wo ich mich befinde. So mache ich es:

d = {'x': 1, 'y': 2, 'z': 3} 
for i, (key, value) in enumerate(d.items()):
   print(i, key, value)

Beachten Sie, dass die Klammern um den Schlüssel wichtig sind. Ohne die Klammern erhalten Sie einen ValueError "Nicht genügend Werte zum Entpacken".

jdhao
quelle
1
Wie ist das für die Frage relevant?
jorijnsmit
8

Sie können die Implementierung von CPython dicttypeauf GitHub überprüfen . Dies ist die Signatur der Methode, die den Diktator implementiert:

_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
             PyObject **pvalue, Py_hash_t *phash)

CPython dictobject.c

Ankur Agarwal
quelle
4

Um über Schlüssel zu iterieren, ist es langsamer, aber besser zu verwenden my_dict.keys(). Wenn Sie versucht haben, so etwas zu tun:

for key in my_dict:
    my_dict[key+"-1"] = my_dict[key]-1

Dies würde einen Laufzeitfehler verursachen, da Sie die Schlüssel ändern, während das Programm ausgeführt wird. Wenn Sie unbedingt Zeit sparen möchten, verwenden Sie den for key in my_dictWeg, aber Sie wurden gewarnt;).

Neil Chowdhury o_O
quelle
2

Dadurch wird die Ausgabe in aufsteigender Reihenfolge nach Werten sortiert gedruckt.

d = {'x': 3, 'y': 1, 'z': 2}
def by_value(item):
    return item[1]

for key, value in sorted(d.items(), key=by_value):
    print(key, '->', value)

Ausgabe:

Geben Sie hier die Bildbeschreibung ein

Amar Kumar
quelle