Comportamiento del iterador de lista de Python y siguiente (iterador)


Considere:

>>> lst = iter([1,2,3])
>>> next(lst)
1
>>> next(lst)
2

Entonces, avanzar el iterador es, como se esperaba, manejado mutando ese mismo objeto.

Siendo Este el caso, yo esperaría:

a = iter(list(range(10)))
for i in a:
   print(i)
   next(a)

Para omitir cada segundo elemento: la llamada a next debe avanzar una vez al iterador, luego la llamada implícita realizada por el bucle debe avanzar una segunda vez, y el resultado de esta segunda llamada se asignará a i.

No. El bucle imprime todos de los elementos de la lista, sin saltando cualquiera.

Mi primer pensamiento fue que esto podría suceder porque el bucle llama iter en lo que se pasa, y esto podría dar un iterador independiente - este no es el caso, como tenemos iter(a) is a.

Entonces, ¿por qué next no parece avanzar el iterador en este caso?

Author: Martijn Pieters, 2013-05-29

6 answers

Lo que ves es el intérprete haciendo eco del valor devuelto de next() además de i siendo impreso cada iteración:

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    next(a)
... 
0
1
2
3
4
5
6
7
8
9

Así que 0 es la salida de print(i), 1 el valor devuelto desde next(), repetido por el intérprete interactivo, etc. Solo hay 5 iteraciones, cada iteración resulta en 2 líneas que se escriben en el terminal.

Si asigna la salida de next() las cosas funcionan como se espera:

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    _ = next(a)
... 
0
2
4
6
8

O imprimir extra información para diferenciar la salida print() del intérprete interactivo echo:

>>> a = iter(list(range(10)))
>>> for i in a:
...    print('Printing: {}'.format(i))
...    next(a)
... 
Printing: 0
1
Printing: 2
3
Printing: 4
5
Printing: 6
7
Printing: 8
9

En otras palabras, next() funciona como se esperaba, pero debido a que devuelve el siguiente valor del iterador, repetido por el intérprete interactivo, se le hace creer que el bucle tiene su propia copia del iterador de alguna manera.

 157
Author: Martijn Pieters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 16:07:02

Lo que está sucediendo es que next(a) devuelve el siguiente valor de a, que se imprime en la consola porque no se ve afectado.

Lo que puede hacer es afectar a una variable con este valor:

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    b=next(a)
...
0
2
4
6
8
 10
Author: njzk2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-29 13:23:23

Encuentro las respuestas existentes un poco confusas, porque solo indican indirectamente la cosa desconcertante esencial en el ejemplo de código: ambos* el "print i" y el "next(a)" están causando que sus resultados se impriman.

Dado que están imprimiendo elementos alternos de la secuencia original, y es inesperado que la instrucción "next(a)" esté imprimiendo, parece como si la instrucción "print i" estuviera imprimiendo todos los valores.

En esa luz, se hace más claro que asignar el resultado de" next(a) "a una variable inhibe la impresión de su resultado, de modo que solo se imprimen los valores alternativos que la variable de bucle" i". Del mismo modo, hacer que la declaración "print" emita algo más distintivo lo desambiguará, también.

(Una de las respuestas existentes refuta las otras porque esa respuesta está teniendo el código de ejemplo evaluado como un bloque, de modo que el intérprete no está reportando los valores intermedios para "next(a)".)

El seductor cosa en responder preguntas, en general, es ser explícito acerca de lo que es obvio una vez que sabes la respuesta. Puede ser difícil de alcanzar. Del mismo modo criticando las respuestas una vez que las entiendas. Es interesante...

 7
Author: klm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-30 14:32:32

Algo está mal con su Python/Computadora.

a = iter(list(range(10)))
for i in a:
   print(i)
   next(a)

>>> 
0
2
4
6
8

Funciona como se espera.

Probado en Python 2.7 y en Python 3+ . Funciona correctamente en ambos

 2
Author: Inbar Rose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-29 13:19:40

Se comporta de la manera que desea si se llama como una función:

>>> def test():
...     a = iter(list(range(10)))
...     for i in a:
...         print(i)
...         next(a)
... 
>>> test()
0
2
4
6
8
 1
Author: burmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-03 17:39:02

Para aquellos que todavía no entienden.

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    next(a)
... 
0 # print(i) printed this
1 # next(a) printed this
2 # print(i) printed this
3 # next(a) printed this
4 # print(i) printed this
5 # next(a) printed this
6 # print(i) printed this
7 # next(a) printed this
8 # print(i) printed this
9 # next(a) printed this

Como otros ya han dicho, next aumenta el iterador en 1 como se esperaba. Asignar su valor devuelto a una variable no cambia mágicamente su comportamiento.

 1
Author: Wesley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 06:48:58