Jestem trochę zdziwiony następującym kodem:

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

Nie rozumiem, to część key. Jak Python rozpoznaje, że musi tylko przeczytać klucz ze słownika? Jest key specjalne słowo w Pythonie? Czy jest po prostu zmienna?

3748
TopChef 21 lipiec 2010, 02:27

10 odpowiedzi

Najlepsza odpowiedź

key to tylko nazwa zmiennej.

for key in d:

Po prostu pętla nad kluczem w słowniku, a nie klucze i wartościach. Aby pętlić zarówno na kluczu, jak i wartości, możesz użyć następujących elementów:

Dla Pythona 3.x:

for key, value in d.items():

Dla Python 2.x:

for key, value in d.iteritems():

Aby przetestować sam, zmień słowo key do poop.

W Pythonie 3.x, {x0}} został zastąpiony po prostu items(), który zwraca widok podobny do ustawionego wspieranego przez dict, jak iteritems(), ale nawet lepiej. Jest to również dostępne w 2,7 jako viewitems().

Operacja items() będzie działać zarówno dla 2, jak i 3, ale w 2 zwróci listę pary (key, value). połączenie. Jeśli chcesz zachowań 2.x w 3.x, możesz zadzwonić list(d.items()).

5726
Jason 3 styczeń 2020, 05:46

Nie jest taki, że klucz jest specjalnym słowem, ale słowniki wdrażają protokół Iteratora. Możesz to zrobić w swojej klasie, np. Zobacz To pytanie do budowy klasy ieratorów.

W przypadku słowników jest realizowany na poziomie C. Szczegóły są dostępne w PEP 234. W szczególności sekcja zatytułowana "Słownik Iteratory":

  • słowniki wdrażają gniazdo TP_IDER, które zwraca wydajność iterator, który jest iteruje nad kluczem w słowniku. [...] to oznacza, że możemy pisać

     for k in dict: ...
     

    , co jest równoważne, ale znacznie szybciej niż

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

    tak długo, jak ograniczenie modyfikacji do słownika (albo przez pętlę lub przez inny wątek) nie są naruszane.

  • dodaj metody do słowników, które zwracają różne rodzaje Iteratory wyraźnie:

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

    Oznacza to, że for x in dict jest shorthand dla for x in dict.iterkeys().

W Pythonie 3 dict.iterkeys() dict.itervalues() i dict.iteritems() nie są już obsługiwane. Użyj dict.keys(), dict.values() i dict.items().

475
jpp 30 listopad 2018, 00:11

Iteruje nad dict iteruje przez klucze w żadnej szczególnej kolejności, jak widać tutaj:

Edytuj: (To jest nie ma już przypadku w Python3.6 , ale zauważ, że jest to , a nie gwarantowany zachowanie

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

Dla twojego przykładu jest lepszy pomysł, aby użyć dict.items():

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

Daje to listę kanałów. Kiedy pętlasz się nad nimi, każda krotka jest rozpakowana do k i v automatycznie:

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

Używanie k i v jako nazwy zmiennych podczas pętli nad dict jest całkiem powszechne, jeśli korpus pętli jest tylko kilka linii. Dla bardziej skomplikowanych pętli może być dobry pomysł, aby używać bardziej opisowych nazw:

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

Dobrym pomysłem jest wejście do zwyczaju stosowania snów formatu:

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))
228
nescius 31 październik 2017, 15:12

key jest po prostu zmienną.

Dla Python2.x :

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

... albo lepiej,

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

Dla Python3.x :

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)
96
ssoler 15 czerwiec 2018, 10:51

Gdy tworzysz słowniki, używając składni for .. in .. - zawsze iteruje na klawiszach (wartości są dostępne za pomocą dictionary[key]).

Aby iterować pary z wartościami kluczowymi, w Pythonie 2 Użyj for k,v in s.iteritems() i w Pythonie 3 for k,v in s.items().

68
Georgy 24 maj 2019, 13:41

Jest to bardzo powszechny zapętlony idiom. in jest operatorem. Po użyciu for key in dict i kiedy musi być for key in dict.keys() patrz David Goodger's Idiomatic Python Artykuł (zarchiwizowana kopia).

37
Georgy 24 maj 2019, 13:52

Iteraing nad słownikami używając pętli "dla"

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

Jak Python rozpoznaje, że musi tylko przeczytać klucz ze słownika? Czy jest kluczowym słowem w Pythonie? Czy jest po prostu zmienna?

To nie tylko pętle for. Ważnym słowem jest "Iterating".

Słownik jest mapowaniem kluczy do wartości:

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

W dowolnym momencie ITEREUSE NIT, ITEREUSE Over The Keys. Nazwa zmiennej key jest przeznaczona tylko do opisywania - i jest dość trafna w tym celu.

Dzieje się tak w rozumieniu listy:

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

Zdarza się, gdy przekazujemy słownik do listy (lub dowolnego innego obiektu typu kolekcji):

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

Sposób, w jaki Python Iterates jest, w kontekście, w którym wymaga, wywołuje metodę __iter__ obiektu (w tym przypadku słownik), który zwraca iterator (w tym przypadku, obiekt Keyterator):

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

Nie powinniśmy zamiast tego używać tych specjalnych metod, użyj odpowiedniej funkcji wbudowanej, aby nazwać go, iter:

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

Iteratorzy mają metodę __next__ - ale nazywamy go z 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

Gdy iterator jest wyczerpany, podnosi StopIteration. W ten sposób Python wie, aby wyjść z pętli for lub zrozumienie listy lub wyrażenie generatora lub innego kontekstu iteracyjnego. Gdy iterator podnosi StopIteration Zawsze go podniesie - jeśli chcesz, aby się zmierzyć, potrzebujesz nowego.

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

Powrót do dyktów

Widzieliśmy dyktowanie w wielu kontekstach. To, co widzieliśmy, jest to, że w każdej chwili, które nasuwamy nad dyktami, dostajemy klucze. Powrót do pierwotnego przykładu:

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

Jeśli zmienimy nazwę zmiennej, nadal dostajemy klucze. Spróbujmy:

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

Jeśli chcemy iterować wartości, musimy użyć metody dyktatów {x0}} lub zarówno dla siebie, .items:

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

W przykładzie, byłoby bardziej wydajne, aby zachować to do takich elementów:

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

Ale dla celów akademickich przykładem pytanie jest w porządku.

24
Aaron Hall 21 czerwiec 2017, 02:51

Mam przypadek użycia, w którym muszę iterować przez dykt, aby uzyskać klucz, parę wartości, także indeks wskazujący, gdzie jestem. Tak to robię:

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

Należy zauważyć, że nawiasy wokół klucza, wartość jest ważna, bez nawiasów, otrzymasz ValueError "Za mało wartości, aby rozpakować".

22
jdhao 2 czerwiec 2017, 15:37

Możesz sprawdzić wdrożenie Cysthon's {x0}} na GitHub. Jest to sygnatura metody, która implementuje DICT Iterator:

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

Cysthon dictobject.c.c.

10
Peter Mortensen 19 maj 2018, 18:38

Aby zachować na kluczykach, jest wolniejszy, ale lepiej używać my_dict.keys(). Jeśli próbowałeś zrobić coś takiego:

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

Utworzyłoby błąd środowiska wykonawczego, ponieważ zmieniasz klucze, gdy uruchomiony jest program. Jeśli jesteś absolutnie ustawiony na czas redukcji, użyj sposobu for key in my_dict, ale zostałeś ostrzeżony;).

5
Neil Chowdhury o_O 31 grudzień 2015, 18:39