Python: una iteración a través de una lista no vacía sin cláusula si viene con las manos vacías. ¿Por qué?

StackOverflow https://stackoverflow.com/questions/703520

Pregunta

¿Cómo puede un iterador sobre una secuencia no vacía, sin filtrado y sin agregación (sum(), etc.), rendimiento nada?

Considere un ejemplo sencillo:

sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)

Esto produce [('a', 97), ('b', 98), ('c', 99)] como se esperaba.

Ahora, sólo intercambiar la ord(el) hacia fuera para una expresión que lleva el primer valor de algún generador usando (...).next() - perdona el ejemplo artificial:

def odd_integers_up_to_length(str):
    return (x for x in xrange(len(str)) if x%2==1)

list((el, odd_integers_up_to_length(el).next()) for el in sequence)

Esto produce []. Sí, lista vacía. No hay tuplas ('a',stuff). Nada.

Pero no estamos filtrando o agregación o reducir. Una expresión generador sobre n objetos sin filtrar o agregación debe ceder objetos n, ¿verdad? ¿Qué está pasando?

¿Fue útil?

Solución

odd_integers_up_to_length(el).next() elevará StopIteration, que no está atrapado allí, pero es atrapado por la expresión generador dentro de ella, deteniéndose sin ceder nunca nada.

vistazo a la primera iteración, cuando el valor es 'a':

>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Otros consejos

Lo que pasa es que la llamada next() lanza una excepción StopIteration, que se propaga hacia arriba de la pila para la expresión externa del generador y se detiene que iteración.

A StopIteration es la forma normal de un repetidor para indicar que se hace. Generalmente no vemos, porque en general la llamada next() se produce dentro de una construcción que consume el iterador, por ejemplo for x in iterator o sum(iterator). Pero cuando llamamos directamente next(), nosotros somos los responsables de controlar el StopIteration. De no hacerlo, surge una fuga en la abstracción, que en este caso lleva a un comportamiento inesperado en la repetición externa.

La lección, supongo: tener cuidado con llamadas directas a next()

.

str es una palabra clave reservada, debe asignar a la variable de manera diferente

También era asesorar sobre el próximo

>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]

Así que no es list que le da problemas aquí ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top