method iter has attribute __iter__ python iterator generator stopiteration

python - has - ¿Por qué a continuación se genera una ''StopIteration'', pero ''for'' hace un retorno normal?



python iter method (1)

En este fragmento de código, ¿por qué el uso de ''for'' no produce ''StopIteration'' o el bucle ''for'' atrapa todas las excepciones y luego sale silenciosamente? ¿En qué caso, por qué tenemos el ''retorno'' extraño? ¿O es el raise StopIteration causado por: return None ?

#!/usr/bin/python3.1 def countdown(n): print("counting down") while n >= 9: yield n n -= 1 return for x in countdown(10): print(x) c = countdown(10) next(c) next(c) next(c)

Suponiendo que StopIteration se desencadena por: return None . ¿Cuándo se genera GeneratorExit?

def countdown(n): print("Counting down from %d" % n) try: while n > 0: yield n n = n - 1 except GeneratorExit: print("Only made it to %d" % n)

Si hago manualmente un:

c = countdown(10) c.close() #generates GeneratorExit??

¿En qué caso, por qué no veo una traza?


El bucle for StopIteration explícitamente StopIteration .

El propósito de la instrucción for es recorrer la secuencia proporcionada por un iterador y la excepción se utiliza para indicar que el iterador está listo; for no captura otras excepciones generadas por el objeto sobre el que se itera, solo esa.

Esto se debe a que StopIteration es la señal normal y esperada que le dice a quien está iterando que no hay nada más que producir.

Una función de generador es un tipo especial de iterador; de hecho, genera StopIteration cuando se realiza la función (es decir, cuando regresa, por lo que sí, return None genera StopIteration ). Es un requisito de los iteradores; deben levantar StopIteration cuando se hacen; de hecho, una vez que se ha levantado un StopIteration , intentar obtener otro elemento de ellos (mediante next() , o llamar al .next() (py 2) o .__next__() (py 3) en el iterador) siempre debe elevar StopIteration nuevo.

GeneratorExit es una excepción para comunicarse en la otra dirección. Está cerrando explícitamente un generador con una expresión de yield , y la forma en que Python comunica ese cierre al generador es mediante la creación de GeneratorExit dentro de esa función. Usted captura explícitamente esa excepción dentro de la countdown , su propósito es permitir que un generador limpie los recursos según sea necesario al cerrar.

Un GeneratorExit no se propaga a la persona que llama; Consulte la documentación de generator.close() .