¿Cómo puedo manejar las excepciones en una lista de comprensión en Python?

Tengo una lista de comprensión en Python en la que cada iteración puede generar una excepción.

Por ejemplo , si tengo:

eggs = (1,3,0,3,2) [1/egg for egg in eggs] 

ZeroDivisionError una excepción ZeroDivisionError en el tercer elemento.

¿Cómo puedo manejar esta excepción y continuar la ejecución de la lista de comprensión?

La única forma en que puedo pensar es usar una función de ayuda:

 def spam(egg): try: return 1/egg except ZeroDivisionError: # handle division by zero error # leave empty for now pass 

Pero esto me parece un poco engorroso.

¿Hay una mejor manera de hacer esto en Python?

Nota: Este es un ejemplo simple (vea ” por ejemplo ” más arriba) que inventé porque mi ejemplo real requiere algo de contexto. No estoy interesado en evitar errores de división por cero, sino en manejar excepciones en una lista de comprensión.

No hay una expresión incorporada en Python que le permita ignorar una excepción (o devolver valores alternos & c en caso de excepciones), por lo que es literalmente imposible “manejar las excepciones en una lista de comprensión” porque una lista de comprensión es una expresión que contiene otra expresión, nada más (es decir, ninguna statement, y solo las declaraciones pueden detectar / ignorar / manejar excepciones).

Las llamadas a funciones son expresión, y los cuerpos de función pueden incluir todas las declaraciones que desee, por lo que delegar la evaluación de la subexpresión propensa a excepciones a una función, como se ha notado, es una solución viable (otras, cuando es posible, son verifica los valores que puedan provocar excepciones, como también se sugiere en otras respuestas).

Las respuestas correctas a la pregunta “cómo manejar las excepciones en una lista de comprensión” expresan parte de toda esta verdad: 1) literalmente, es decir, léxicamente EN la comprensión en sí, no se puede; 2) en la práctica, delegas el trabajo a una función o verificas valores propensos a errores cuando sea posible. Su afirmación reiterada de que esto no es una respuesta es, por lo tanto, infundada.

Me doy cuenta de que esta pregunta es bastante antigua, pero también puede crear una función general para facilitar este tipo de cosas:

 def catch(func, handle=lambda e : e, *args, **kwargs): try: return func(*args, **kwargs) except Exception as e: return handle(e) 

Luego, en tu comprensión:

 eggs = (1,3,0,3,2) [catch(lambda : 1/egg) for egg in eggs] [1, 0, ('integer division or modulo by zero'), 0, 0] 

Por supuesto, puede hacer que la función predeterminada del controlador sea lo que desee (supongamos que prefiere devolver ‘Ninguno’ de forma predeterminada).

Espero que esto te ayude a ti o a los futuros espectadores de esta pregunta!

Nota: en python 3, haría que la palabra clave del argumento ‘manejar’ solo, y la pusiera al final de la lista de argumentos. Esto haría que los argumentos pasantes y, por lo tanto, la captura mucho más natural.

Puedes usar

 [1/egg for egg in eggs if egg != 0] 

esto simplemente saltará los elementos que son cero.

No hay mejor manera. En muchos casos puedes usar la evitación como lo hace Peter

Tu otra opción es no utilizar las comprensiones.

 eggs = (1,3,0,3,2) result=[] for egg in eggs: try: result.append(egg/0) except ZeroDivisionError: # handle division by zero error # leave empty for now pass 

Depende de usted decidir si eso es más engorroso o no

Creo que una función de ayuda, tal como lo sugiere el que hace la pregunta inicial y Bryan Head también, es buena y no es para nada complicada. Una sola línea de código mágico que hace todo el trabajo no siempre es posible, por lo que una función de ayuda es una solución perfecta si uno quiere evitar bucles. Sin embargo lo modificaría a éste:

 # A modified version of the helper function by the Question starter def spam(egg): try: return 1/egg, None except ZeroDivisionError as err: # handle division by zero error return None, err 

La salida será este [(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)] . Con esta respuesta, usted tiene el control total para continuar de la manera que desee.