Eu sunt un pic nedumerit de următorul cod:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
Ceea ce nu't înțeles este "cheia" parte. Cum Python recunoaște că este nevoie doar de a citi cheia din dicționar? Este "cheia" un cuvânt special în Python? Sau este pur și simplu o variabilă?
"cheia" este doar un nume de variabilă.
for key in d:
pur și simplu va bucla peste cheile în dicționar, mai degrabă decât de chei și valori. La bucla peste ambele cheie și valoarea puteți utiliza următoarele:
Pentru Python 2.x:
for key, value in d.iteritems():
Pentru Python 3.x:
for key, value in d.items():
Pentru a testa pentru tine, schimba cuvantul "cheie" a caca
.
Pentru Python 3.x, iteritems()
a fost înlocuit cu pur și simplu elemente (), care returnează un set-ca opinia susținută de către dict, ca
iteritems()dar chiar mai bine. Acest lucru este, de asemenea, disponibil în 2.7
viewitems()`.
Operațiunea de elemente()va lucra atât pentru 2 și 3, dar în 2 se va returna o listă de dicționar's
(cheie, valoare)perechi, care nu va reflecta modificările dict asta să se întâmple după
elemente()apel. Dacă doriți 2.x comportament în 3.x, puteți apela lista(d.elemente())
.
L's nu acea cheie este un cuvânt special, dar dicționare pună în aplicare iterator protocol. Ai putea face acest lucru în clasă, de exemplu, a se vedea această întrebare pentru modul de a construi clasa iteratori.
În caz de dicționare, l's, implementat la nivelul C. Detaliile sunt disponibile în PEP 234. În special, secțiunea intitulată "Dicționar Iteratori":
- Dicționare pună în aplicare o tp_iter slot care returnează un mod eficient iterator care reiterează peste cheile de dicționar. [...] Acest înseamnă că putem scrie
pentru k in dict: ...
care este echivalent cu a, dar mult mai repede decât
pentru k in dict.tastele(): ...
atâta timp cât restricție privind modificări în dicționar (fie prin bucla sau de către un alt thread) nu sunt încălcate.
- se Adaugă metode de dicționare care se întorc diferite tipuri de iteratori în mod explicit:
pentru cheie în dict.iterkeys(): ...
pentru valoarea în dict.itervalues(): ...
pentru cheie, valoare în dict.iteritems(): ...
Acest lucru înseamnă că, pentru x în dict
este prescurtarea pentru
x în dict.iterkeys()`.
În Python 3, dict.iterkeys()
, dict.itervalues () " și " dict.iteritems()
nu mai sunt acceptate. Folosesc dict.tastele(),
dict.valorile () " și " dict.elemente()` în loc.
Iterarea peste un dict` reiterează prin cheile în nici o ordine special, după cum puteți vedea aici:
Edit: (Asta e nu mai este cazul, în Python3.6, dar rețineți că l's nu este garantat comportamentul încă)
>>> d = {'x': 1, 'y': 2, 'z': 3}
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']
De exemplu, este o idee bună pentru a folosi dict.elemente()`:
>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]
Acest lucru vă oferă o listă de tupluri. Atunci când bucla peste ele astfel, fiecare tuplu este despachetat în " k " și " v " în mod automat:
for k,v in d.items():
print(k, 'corresponds to', v)
Folosind " k " și " v " ca nume de variabile, atunci când looping peste un dict` este destul de comună în cazul în care corpul buclei este de numai câteva rânduri. Pentru mai complicat bucle poate fi o idee bună să utilizați nume mai descriptive:
for letter, number in d.items():
print(letter, 'corresponds to', number)
L's o idee bună pentru a obține în obiceiul de a folosi format siruri de caractere:
for letter, number in d.items():
print('{0} corresponds to {1}'.format(letter, number))
"cheia" este pur și simplu o variabilă.
Pentru Python2.X:
d = {'x': 1, 'y': 2, 'z': 3}
for my_var in d:
print my_var, 'corresponds to', d[my_var]
... sau mai bine,
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.iteritems():
print the_key, 'corresponds to', the_value
Pentru Python3.X:
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.items():
print(the_key, 'corresponds to', the_value)
Atunci când repeta prin dicționare, folosind de .. in ..
-sintaxă, întotdeauna reiterează peste cheile (valorile sunt accesibile folosind în dicționarul[cheie]
).
Pentru a itera peste perechi cheie-valoare, în Python 2 utilizați pentru k,v în s.iteritems(), și în Python 3
pentru k,v în s.elemente()`.
Aceasta este o foarte frecvente looping expresie. " în " este un operator. Pentru atunci când pentru a utiliza pentru cheie în dictși când trebuie să fie pentru cheie în dict.tastele()
vezi David Goodger's Idiomatice Python articolul (copie arhivată).
Am un caz de utilizare în cazul în care trebuie să itera prin dict pentru a obține cheia, valoarea pereche, de asemenea, indicele care indică unde sunt. Acest lucru este cum am face-o:
d = {'x': 1, 'y': 2, 'z': 3}
for i, (key, value) in enumerate(d.items()):
print(i, key, value)
Rețineți că paranteze în jurul valorii de cheie, valoarea este important, fără paranteze, veți obține o ValueError "nu destul de valori pentru a despacheta".
Iterarea peste dicționare, folosind 'pentru' bucle
d = {'x': 1, 'y': 2, 'z': 3} pentru cheie in d: ...
Cum Python recunoaște că este nevoie doar de a citi cheia de la dicționar? Cheia este un cuvânt special în Python? Sau este pur și simplu o variabila?
L's nu doar pentru bucle. Cuvântul important aici este "iterarea".
Un dicționar este o mapare de chei de la valorile:
d = {'x': 1, 'y': 2, 'z': 3}
În orice moment ne-am repeta peste asta, vom repeta peste cheile. Numele variabilei "cheie" este destinat numai pentru a fi descriptiv - și este destul de apt pentru acest scop.
Acest lucru se întâmplă într-o listă de înțelegere:
>>> [k for k in d]
['x', 'y', 'z']
Se întâmplă atunci când vom trece dicționar de listă (sau orice alt tip de colectare obiect):
>>> list(d)
['x', 'y', 'z']
Modul Python reiterează, într-un context în care acesta are nevoie pentru a, se numește __iter__
metoda a obiectului (în acest caz, dicționar) care întoarce un iterator (în acest caz, o keyiterator obiect):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
Ar trebui't de a folosi aceste metode speciale noi, în schimb, folosiți built-in funcția de a spune, iter
:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
Iteratori au o __următorii__
metoda - dar noi o numim cu funcție nativă, "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
Atunci când un iterator este epuizat, se ridică StopIteration
. Acesta este modul Python știe la ieșire o pentru buclă, sau o listă de înțelegere, sau un generator de exprimare, sau orice alte iterativ context. Odată ce un iterator ridică StopIteration
se va ridica mereu - dacă doriți pentru a repeta din nou, ai nevoie de unul nou.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Am'am vazut dicts iterarea în multe contexte. Ceea ce ne'am văzut este că în orice moment ne-am repeta peste un dict, vom obține cheile. Înapoi la original, de exemplu:
d = {'x': 1, 'y': 2, 'z': 3} pentru cheie in d:
Dacă ne-am schimba numele variabilei, am încă pentru a obține cheile. Las's încercați să-l:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Dacă vrem să itera peste valorile, avem nevoie pentru a utiliza .valorile metoda de dicts, sau pentru ambele împreună.articole
:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
În exemplul dat, ar fi mult mai eficient pentru a itera peste articole de genul asta:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Dar pentru scopuri academice, întrebarea's de exemplu este bine.
Puteți verifica punerea în aplicare a CPython's `dicttype pe GitHub. Aceasta este semnătura metoda care implementează dict iterator:
_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
PyObject **pvalue, Py_hash_t *phash)
Pentru a itera peste chei, este mai lent dar mai bine să utilizați my_dict.tastele()
. Dacă ai încercat să faci ceva de genul asta:
for key in my_dict:
my_dict[key+"-1"] = my_dict[key]-1
s-ar crea o eroare de execuție pentru că se schimbă cheile în timp ce programul se execută. Dacă sunteți absolut stabilit reducerea de timp, utilizați pentru cheie în my_dict, dar ai fost avertizat ;).