Pregunta Iteración sobre diccionarios que usan 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 el key parte. ¿Cómo reconoce Python que solo necesita leer la clave del diccionario? Es key una palabra especial en Python? ¿O es simplemente una variable?


2105
2017-07-20 22:27


origen


Respuestas:


key es solo un nombre de variable.

for key in d:

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

Para Python 2.x:

for key, value in d.iteritems():

Para Python 3.x:

for key, value in d.items():

Para probarse a sí mismo, cambie la palabra key a poop.

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

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


3784
2017-07-20 22:29



No es que esa clave sea una palabra especial, sino que los diccionarios implementan el protocolo de iterador. Puedes hacer esto en tu clase, p. ver esta pregunta para 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 "Iteradores del diccionario":

  • Los diccionarios implementan una ranura tp_iter que devuelve un eficiente   iterador que itera sobre las teclas del diccionario. [...] Esta   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 la restricción de modificaciones en el diccionario   (ya sea por el bucle o por otro hilo) no se violan.

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

    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().


325
2017-07-20 23:52



Iterando sobre un dict itera a través de sus teclas sin ningún orden en particular, como puede ver aquí:

Editar: (Esto es ya no es el caso en Python3.6, pero tenga en cuenta que es no garantizado comportamiento aún)

>>> 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 te da una lista de tuplas. Cuando les das la vuelta así, cada tupla se desempaqueta en k y v automáticamente:

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

Utilizando k y v como nombres de variables cuando se repite sobre un dict es bastante común si el cuerpo del bucle es de solo 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 adquirir el hábito de usar cadenas de formato:

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

151
2017-07-21 01:27



key es simplemente una variable.

por 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

por Python3.X:

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

42
2017-07-20 23:49



Cuando itera a través de diccionarios usando el for .. in ..-sintaxis, siempre itera sobre las teclas (los valores son accesibles usando dictionary[key])

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


39
2017-07-20 22:29



Esta es una expresión idiomática muy común. in es un operador. Para cuando usar for key in dict y cuando debe ser for key in dict.keys() ver Artículo Idiomatic Python de David Goodger.


20
2017-07-20 22:42



Puedes usar esto:

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

9
2018-01-14 14:42



Tengo un caso de uso en el que tengo que repetir el dict para obtener la clave, el par de valores y 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 el paréntesis alrededor de la clave, el valor es importante, sin los paréntesis, se obtiene un ValueError "no hay valores suficientes para descomprimir".


6
2018-05-25 13:42



Iteración sobre diccionarios que usan 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 un   ¿variable?

No es solo for bucles. La palabra importante aquí es "iterar".

Un diccionario es un mapeo de las claves de los 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 tiene la intención de ser descriptivo, y es bastante apropiado 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 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 utilizar estos métodos especiales nosotros mismos, en su lugar, use la función interna respectiva para llamarlo, iter:

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

Iteradores tienen un __next__ método - 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 está agotado, aumenta StopIteration. Así es como Python sabe salir de un for loop, o una lista de comprensión, o una expresión de generador, o cualquier otro contexto iterativo. Una vez que sube un iterador StopIteration siempre lo elevará; si desea iterar 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 dicts que se repiten en muchos contextos. Lo que hemos visto es que cada vez que iteramos sobre un dict, obtenemos las claves. Volver al ejemplo original:

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

Si cambiamos el nombre de la variable, todavía 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 dicts, 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.


4
2018-06-21 02:51



Puede verificar la implementación de CPython dicttype 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


3
2017-11-03 05:16