web-dev-qa-db-esp.com

Iterando sobre los diccionarios usando bucles 'for'

Estoy un poco desconcertado por el siguiente código:

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

Lo que no entiendo es la porción de key. ¿Cómo reconoce Python que solo necesita leer la clave del diccionario? ¿Es key una palabra especial en Python? ¿O es simplemente una variable?

2665
TopChef

key es solo un nombre de variable.

for key in d:

simplemente pasará sobre las claves en el diccionario, en lugar de las claves y los valores. Para recorrer tanto la clave como el valor, puede utilizar lo siguiente:

Para Python 2.x:

for key, value in d.iteritems():

Para Python 3.x:

for key, value in d.items():

Para probar por ti mismo, cambia la Palabra key a poop.

Para Python 3.x, iteritems() ha sido reemplazado por simplemente items(), que devuelve una vista similar a un conjunto respaldada por el dict, como iteritems() pero aún mejor. Esto también está disponible en 2.7 como viewitems().

La operación items() funcionará tanto para 2 como para 3, pero en 2 devolverá una lista de los pares (key, value) del diccionario, que no reflejarán los cambios en el dict que suceden después de la llamada items(). Si desea el comportamiento 2.x en 3.x, puede llamar a list(d.items()).

4718
sberry

No es que la clave sea una palabra especial, sino que los diccionarios implementan el protocolo iterador. Puedes hacer esto en tu clase, por ejemplo. vea esta pregunta para saber cómo construir iteradores de clase.

En el caso de los diccionarios, se implementa en el nivel C. Los detalles están disponibles en PEP 234 . En particular, la sección titulada "Diccionario Iteradores":

  • Los diccionarios implementan una ranura tp_iter que devuelve un iterador eficiente que recorre las claves del diccionario. [...] Esto significa que podemos escribir

    for k in dict: ...
    

    que es equivalente a, pero mucho más rápido que

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

    siempre que no se viole la restricción de modificaciones al diccionario (ya sea por el bucle o por otro hilo).

  • Agregue métodos a los diccionarios que devuelven explícitamente diferentes tipos de iteradores:

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

    Esto significa que for x in dict es una abreviatura de for x in dict.iterkeys().

En Python 3, dict.iterkeys(), dict.itervalues() y dict.iteritems() ya no son compatibles. Utilice dict.keys(), dict.values() y dict.items() en su lugar.

384
ars

Iterar sobre una dict itera a través de sus claves sin ningún orden en particular, como puede ver aquí:

Edición: (Esto es ya no es el caso en Python3.6, pero tenga en cuenta que es no está garantizado comportamiento todavía)

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

Para su ejemplo, es una mejor idea usar dict.items():

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

Esto le da una lista de tuplas. Cuando los recorres de esta forma, cada tupla se desempaqueta en k y v automáticamente:

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

El uso de k y v como nombres de variables cuando se realiza un bucle sobre una dict es bastante común si el cuerpo del bucle es solo de unas pocas líneas. Para bucles más complicados, puede ser una buena idea usar nombres más descriptivos:

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

Es una buena idea acostumbrarse a usar cadenas de formato:

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))
181
John La Rooy

key es simplemente una variable.

Para Python2.X :

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

... o mejor,

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

Para Python3.X :

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

Cuando recorre los diccionarios utilizando la sintaxis for .. in ..-, siempre itera sobre las claves (los valores son accesibles usando dictionary[key]).

Para iterar sobre pares clave-valor, use for k,v in s.iteritems().

49
Alexander Gessler

Este es un lenguaje bucle muy común. in es un operador. Para saber cuándo usar for key in dict y cuándo debe ser for key in dict.keys(), vea Artículo Idiomatic Python de David Goodger .

26
chryss

Puedes usar esto:

for key,val in d.items():
    print key, 'is the key for ', val
16

Tengo un caso de uso en el que tengo que recorrer el dictado para obtener la clave, el par de valores y también el índice que indica dónde estoy. Así es como lo hago:

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

Tenga en cuenta que los paréntesis alrededor de la clave, el valor es importante, sin los paréntesis, obtendrá un ValueError "no hay suficientes valores para descomprimir".

12
jdhao

lo que sea, hoy, tanto python 2.6 y 2.7, como 3.x, en mi caja funcionan bien con items():

z = {0: 'a', 1: 'b'}
for k, v in z.items(): print(v, k)
12
象嘉道

Iterando sobre los 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 la clave una palabra especial en Python? ¿O es simplemente una variable?

No se trata solo de for bucles. La palabra importante aquí es "iterando".

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 adecuado para este propósito.

Esto sucede en una lista de comprensión:

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

Ocurre 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 necesita, llama al método __iter__ 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, 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 método __next__, pero lo llamamos con la función incorporada, 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, aumenta StopIteration. Así es como Python sabe salir de un bucle for, una lista de comprensión, una expresión generadora o cualquier otro contexto iterativo. Una vez que un iterador genera StopIteration siempre lo aumentará: si desea repetir una vez más, necesita uno nuevo.

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

Volviendo a los dictados

Hemos visto los dictados iterando en muchos contextos. Lo que hemos visto es que cada vez que repetimos un dictado, obtenemos las claves. De vuelta al ejemplo original:

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

Si cambiamos el nombre de la variable, seguimos obteniendo 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 método de dicts .values, 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 propósitos académicos, el ejemplo de la pregunta está bien.

11
Aaron Hall

Puede verificar la implementación de la dicttype de CPython en GitHub. Esta es la firma del método que implementa el iterador dict:

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

CPython dictobject.c

7
abc

Para iterar sobre las teclas, es más lento, pero es mejor usar my_dict.keys(). Si intentaste hacer algo como esto:

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

se crearía un error de tiempo de ejecución porque está cambiando las claves mientras el programa se está ejecutando. Si está absolutamente decidido a reducir el tiempo, use el método for key in my_dict, pero se le ha advertido;).

2
Neil Chowdhury o_O

Para clave en my_dict es en realidad igual para clave en my_dict.keys (). Así que si quieres obtener valores de dict, puedes probar dos métodos.

Uno:

for value in my_dict.values():
    print(value)

Dos:

for key in my_dict:
    print(my_dict[key])
1
Amaan Durrani

Sugerencia de impresión para valores largos
Si tiene cadenas largas en los valores, aquí hay una manera rápida de imprimir esto en un (¿más?) Formato legible:
for key, value in my_dictionary.iteritems(): print(key) print("---------") print(value) print("\n")

0
Joseph True