¿Por qué los iteradores en Python generan una excepción?

47

Aquí está la sintaxis para los iteradores en Java (sintaxis algo similar en C #):

Iterator it = sequence.iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}

Lo que tiene sentido. Aquí está la sintaxis equivalente en Python:

it = iter(sequence)
while True:
    try:
        value = it.next() 
    except StopIteration:
        break
    print(value)

Pensé que se suponía que las excepciones debían usarse solo en circunstancias excepcionales.

¿Por qué Python usa excepciones para detener la iteración?

    
pregunta NullUserException 05.10.2011 - 04:03

4 respuestas

50

Hay una forma muy pitónica de escribir esa expresión sin escribir explícitamente un bloque try-except para un StopIteration :

# some_iterable is some collection that can be iterated over
# e.g., a list, sequence, dict, set, itertools.combination(...)

for value in some_iterable:
    print value

Puede leer los PEP relevantes 234 255 si desea saber más sobre por qué se introdujo StopIteration y la lógica detrás de los iteradores.

Un principio general en python es tener una forma de hacer algo (ver import this ), y preferiblemente es hermoso, explícito, legible y simple, que cumple el método pythonic. Su código equivalente solo es necesario, ya que python no otorga a los iteradores una función miembro hasNext ; prefiriendo que las personas simplemente recorran los iteradores directamente (y si necesitas hacer algo más para intentar leerlo y obtener una excepción).

Esta captura automática de una excepción StopIteration al final de un iterador tiene sentido y es un análogo del EOFError generado si lees más allá de un final de archivo.

    
respondido por el dr jimbob 05.10.2011 - 04:44
28

La razón por la que Python usa una excepción para detener una iteración se documenta en PEP 234 :

  

Se ha cuestionado si una excepción para señalar el final de       La iteración no es demasiado cara. Varias alternativas para el       Se ha propuesto la excepción StopIteration: un valor especial Fin       para señalar el final, una función end () para probar si el iterador       está terminado, incluso reutilizando la excepción IndexError.

     
  • Un valor especial tiene el problema de que si alguna vez una secuencia   contiene ese valor especial, un bucle sobre esa secuencia   Termina prematuramente sin previo aviso. Si la experiencia con   las cadenas en C terminadas en nulo no nos han enseñado los problemas de este   puede causar, imagina el problema de una herramienta de introspección de Python   tendría iterando sobre una lista de todos los nombres incorporados,   ¡asumiendo que el valor final especial era un nombre incorporado!

  •   
  • Llamar a una función end () requeriría dos llamadas por   iteración. Dos llamadas son mucho más caras que una llamada   más una prueba para una excepción. Especialmente el tiempo crítico.   for loop puede probar muy barato para una excepción.

  •   
  • Reutilizar IndexError puede causar confusión porque puede ser una   Error genuino, que se enmascararía al finalizar el bucle   prematuramente.

  •   

Nota: la forma idiomática de Python para recorrer una secuencia es la siguiente:

for value in sequence:
    print (value)
    
respondido por el lesmana 07.12.2012 - 08:59
20

Es una diferencia en filosofía. La filosofía de diseño de Pythonic es EAFP :

  

Más fácil pedir perdón que permiso. Este estilo de codificación de Python común asume la existencia de claves o atributos válidos y captura excepciones si la suposición es falsa. Este estilo limpio y rápido se caracteriza por la presencia de muchas declaraciones try y except . La técnica contrasta con el estilo LBYL común a muchos otros idiomas como como C ...

    
respondido por el Charles E. Grant 05.10.2011 - 04:36
7

Es solo que la implementación de Java tiene un método hasNext() para que pueda verificar si hay un iterador vacío antes de realizar un next() . Cuando llama a next() en un iterador Java sin elementos, NoSuchElementException se lanza .

Así que efectivamente, puedes hacer un try..catch en Java como el try..except en Python. Y sí, según una respuesta anterior, la filosofía es muy importante en el mundo de Pythonic.

    
respondido por el yati sagade 05.10.2011 - 04:46

Lea otras preguntas en las etiquetas