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]
Obtendré una ZeroDivisionError
excepción en el tercer elemento.
¿Cómo puedo manejar esta excepción y continuar la ejecución de la comprensión de la lista?
La única forma en que puedo pensar es usar una función auxiliar:
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.
¿Existe una mejor manera de hacer esto en Python?
Nota: Este es un ejemplo simple (ver " por ejemplo " arriba) que ideé porque mi ejemplo real requiere algo de contexto. No me interesa evitar la división por cero errores, sino manejar las excepciones en una lista de comprensión.
python
exception
list-comprehension
Nathan Fellman
fuente
fuente
[1/egg except ZeroDivisionError: None for egg in (1,3,0,3,2)]
. Pero todavía está en modo borrador. Mi instinto es que no será aceptado. En mi opinión, las expresiones pueden volverse demasiado confusas (verificar múltiples excepciones, tener combinaciones más complejas (múltiples operadores lógicos, comprensiones complejas, etc.)ndarray
con la configuración adecuada ennp.seterr
. Eso daría como resultado1/0 = nan
. Pero me doy cuenta de que eso no se generaliza a otras situaciones en las que surge esta necesidad.Respuestas:
No hay una expresión incorporada en Python que le permita ignorar una excepción (o devolver valores alternativos & c en caso de excepciones), por lo que es imposible, literalmente hablando, "manejar excepciones en una comprensión de lista" porque una comprensión de lista es una expresión que contiene otra expresión, nada más (es decir, no hay declaraciones, y solo las declaraciones pueden detectar / ignorar / manejar excepciones).
Las llamadas a funciones son expresiones, y los cuerpos de las funciones 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 ha notado, es una solución alternativa viable (otras, cuando es factible, son verifica los valores que podrían provocar excepciones, como también se sugiere en otras respuestas).
Las respuestas correctas a la pregunta "cómo manejar las excepciones en una comprensión de lista" están expresando parte de toda esta verdad: 1) literalmente, es decir, léxicamente EN la comprensión misma, no se puede; 2) prácticamente, delega el trabajo a una función o verifica los valores propensos a errores cuando es factible. Por tanto, su reiterada afirmación de que esto no es una respuesta carece de fundamento.
fuente
[x[1] for x in list except IndexError pass]
. ¿No podría el intérprete crear una función temporal para probarx[1]
?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:
Entonces, en tu comprensión:
Por supuesto, puede hacer que la función de control predeterminada sea lo que desee (digamos 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 solo la palabra clave del argumento 'handle' y la pondría al final de la lista de argumentos. Esto haría que los argumentos de paso y la captura de datos sean mucho más naturales.
fuente
args
ykwargs
manejar también. De esa forma, podría devolver decir enegg
lugar de un código fijo0
o una excepción como lo está haciendo.handle
después**kwarg
y obtuve unSyntaxError
. ¿Quiere desreferenciar comokwargs.get('handle',e)
?Puedes usar
esto simplemente omitirá los elementos que son cero.
fuente
No, no hay mejor manera. En muchos casos, puedes usar la evasión como lo hace Peter.
Tu otra opción es no usar comprensiones
Depende de usted decidir si eso es más engorroso o no
fuente
Creo que una función de ayuda, como sugirió el que hace la pregunta inicial y también Bryan Head, es buena y no es engorrosa en absoluto. Una sola línea de código mágico que hace todo el trabajo no siempre es posible, por lo que una función auxiliar es una solución perfecta si se quiere evitar
for
bucles. Sin embargo, lo modificaría a este:La salida será esta
[(1/1, None), (1/3, None), (None, ZeroDivisionError), (1/3, None), (1/2, None)]
. Con esta respuesta, tiene el control total para continuar de la forma que desee.fuente
Either
tipo en algunos lenguajes de programación funcional (como Scala), donde unEither
puede contener un valor de un tipo u otro, pero no de ambos. La única diferencia es que en esos idiomas es idiomático poner el error en el lado izquierdo y el valor en el lado derecho. Aquí hay un artículo con más información .No vi ninguna respuesta que mencionara esto. Pero este ejemplo sería una forma de evitar que se genere una excepción para casos fallidos conocidos.
fuente