Iterando sobre diccionarios usando bucles 'for'
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
...
¿Cómo reconoce Python que solo necesita leer la clave del diccionario? ¿Es clave una palabra especial en Python? ¿O es simplemente una variable?
No son solo for
bucles. La palabra importante aquí es "iterar".
Un diccionario es un mapeo de claves a valores:
d = {'x': 1, 'y': 2, 'z': 3}
Cada vez que iteramos sobre él, iteramos sobre las teclas. El nombre de la variable key
solo pretende ser descriptivo, y es bastante apto para este propósito.
Esto sucede en una lista de comprensión:
>>> [k for k in d]
['x', 'y', 'z']
Sucede cuando pasamos el diccionario a la lista (o cualquier otro objeto de tipo de colección):
>>> list(d)
['x', 'y', 'z']
La forma en que Python itera es, en un contexto donde lo necesita, llama al __iter__
método del objeto (en este caso, el diccionario) que devuelve un iterador (en este caso, un objeto keyiterator):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
No deberíamos usar estos métodos especiales nosotros mismos, en su lugar, use la función incorporada respectiva para llamarlo iter
:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
Los iteradores tienen un __next__
método, pero lo llamamos con la función integrada 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
Cuando un iterador se agota, se eleva StopIteration
. Así es como Python sabe salir de un for
bucle, o una comprensión de la lista, o una expresión generadora, o cualquier otro contexto iterativo. Una vez StopIteration
que se eleva un iterador , siempre lo elevará; si desea repetir nuevamente, necesita uno nuevo.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Volviendo a los dictados
Hemos visto dictados iterando en muchos contextos. Lo que hemos visto es que cada vez que iteramos sobre un dict, obtenemos las claves. Regresando al ejemplo original:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
Si cambiamos el nombre de la variable, aún obtenemos las claves. Vamos a intentarlo:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Si queremos iterar sobre los valores, necesitamos usar el .values
método de dictados, o para ambos juntos .items
:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
En el ejemplo dado, sería más eficiente iterar sobre los elementos como este:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Pero para fines académicos, el ejemplo de la pregunta está bien.