Iterowanie po słownikach za pomocą pętli „for”
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
...
Jak Python rozpoznaje, że wystarczy tylko odczytać klucz ze słownika? Czy klucz to specjalne słowo w Pythonie? Czy jest to po prostu zmienna?
To nie tylko for
pętle. Ważnym słowem jest tutaj „iteracja”.
Słownik to mapowanie kluczy na wartości:
d = {'x': 1, 'y': 2, 'z': 3}
Za każdym razem, gdy wykonujemy iterację, iterujemy po klawiszach. Nazwa zmiennej key
ma jedynie charakter opisowy - i jest całkiem trafna do tego celu.
Dzieje się tak w przypadku zrozumienia listy:
>>> [k for k in d]
['x', 'y', 'z']
Dzieje się tak, gdy przekazujemy słownik do listy (lub dowolnego innego obiektu typu kolekcji):
>>> list(d)
['x', 'y', 'z']
Sposób, w jaki Python wykonuje iterację, w kontekście, w którym musi, wywołuje __iter__
metodę obiektu (w tym przypadku słownika), który zwraca iterator (w tym przypadku obiekt keyiteratora):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
Nie powinniśmy sami korzystać z tych specjalnych metod, zamiast tego użyj odpowiedniej funkcji wbudowanej, aby ją wywołać iter
:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
Iteratory mają __next__
metodę - ale nazywamy ją wbudowaną funkcją 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
Kiedy iterator jest wyczerpany, podnosi się StopIteration
. W ten sposób Python wie, jak wyjść z for
pętli, ze zrozumienia listy, wyrażenia generatora lub dowolnego innego kontekstu iteracyjnego. Gdy iterator podniesie StopIteration
, zawsze go podniesie - jeśli chcesz powtórzyć iterację, potrzebujesz nowego.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Wracając do dykt
Widzieliśmy powtarzające się dyktaty w wielu kontekstach. Zauważyliśmy, że za każdym razem, gdy powtarzamy dyktando, dostajemy klucze. Powrót do oryginalnego przykładu:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
Jeśli zmienimy nazwę zmiennej, nadal otrzymamy klucze. Spróbujmy:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Jeśli chcemy iterować po wartościach, musimy zastosować .values
metodę dyktowania lub dla obu razem .items
:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
W podanym przykładzie bardziej efektywne byłoby iterowanie takich elementów:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Ale dla celów akademickich przykład tego pytania jest w porządku.