¿Debo probar que ifalgo es válido o simplemente tryhacerlo y detectar la excepción?
- ¿Existe alguna documentación sólida que diga que se prefiere una forma?
- ¿Es una forma más pitónica ?
Por ejemplo, debería:
if len(my_list) >= 4:
x = my_list[3]
else:
x = 'NO_ABC'
O:
try:
x = my_list[3]
except IndexError:
x = 'NO_ABC'
Algunas reflexiones ...
PEP 20 dice:
Los errores nunca deben pasar en silencio.
A menos que sea silenciado explícitamente.
¿Debería usarse un en trylugar de un ifcomo un error que pasa silenciosamente? Y si es así, ¿lo está silenciando explícitamente al usarlo de esta manera, por lo tanto, está bien?
Estoy no se refiere a situaciones en las que sólo se puede hacer las cosas 1 manera; por ejemplo:
try:
import foo
except ImportError:
import baz

if index in mylistprueba si el índice es un elemento de mylist, no un índice posible. Te gustaría en suif index < len(mylist)lugar.if/elsequetry/catchEn este caso particular, debe usar algo completamente distinto:
Sin embargo, en general: si espera que la prueba falle con frecuencia, úsela
if. Si la prueba es costosa en relación con solo intentar la operación y detectar la excepción si falla, úselatry. Si ninguna de estas condiciones se aplica, vaya con lo que sea más fácil de leer.fuente
El uso
tryyexceptdirectamente en lugar de dentro de unifguardia siempre debe hacerse si existe alguna posibilidad de una condición de carrera. Por ejemplo, si desea asegurarse de que existe un directorio, no haga esto:Si otro hilo o proceso crea el directorio entre
isdirymkdir, saldrá. En cambio, haz esto:Eso solo saldrá si no se puede crear el directorio 'foo'.
fuente
Si es trivial verificar si algo fallará antes de hacerlo, probablemente debería favorecerlo. Después de todo, la construcción de excepciones (incluidas las trazas asociadas) lleva tiempo.
Se deben usar excepciones para:
breakno lo lleva lo suficientemente lejos), o ...Tenga en cuenta que a menudo, la respuesta real es "ninguna"; por ejemplo, en su primer ejemplo, lo que realmente debe hacer es usar
.get()para proporcionar un valor predeterminado:fuente
if 'ABC' in myDict: x = myDict['ABC']; else: x = 'NO_ABC'realidad, suele ser más rápido que usarget, desafortunadamente. No decir que este es el criterio más importante, pero es algo a tener en cuenta.if / elseytry / exceptpuede tener su lugar incluso cuando hay alternativas específicas para cada caso porque tienen diferentes características de rendimiento..get()es la búsqueda de atributos y la sobrecarga de llamadas a funciones en el nivel de Python; el uso de palabras clave en los elementos integrados básicamente va directamente a C. No creo que vaya a ser mucho más rápido en el corto plazo. En cuanto aifvs.try, el método read dict.get () devuelve un puntero que tiene información de rendimiento. La proporción de aciertos y errores es importante (trypuede ser más rápida si la clave casi siempre existe) al igual que el tamaño del diccionario.Como mencionan las otras publicaciones, depende de la situación. Existen algunos peligros con el uso de try / except en lugar de verificar la validez de sus datos por adelantado, especialmente cuando se usa en proyectos más grandes.
por ejemplo, suponga que tiene:
IndexError no dice nada acerca de si ocurrió al intentar obtener un elemento de index_list o my_list.
fuente
Usar
tryes reconocer que puede pasar un error, que es lo opuesto a que pase en silencio. El usoexceptestá causando que no pase en absoluto.Usando
try: except:se prefiere en los casos en queif: else:la lógica es más complicado. Simple es mejor que complejo; Complejo es mejor que complicado; y es más fácil pedir perdón que permiso.Lo que advierte "los errores nunca deben pasar en silencio" es el caso en el que el código podría generar una excepción que usted conoce y donde su diseño admite la posibilidad, pero no ha diseñado de una manera para lidiar con la excepción. En mi opinión, silenciar explícitamente un error sería hacer algo como
passen unexceptbloque, que solo debe hacerse con el entendimiento de que "no hacer nada" es realmente el manejo correcto de errores en una situación particular. (Esta es una de las pocas veces en que siento que un comentario en un código bien escrito probablemente sea realmente necesario).Sin embargo, en su ejemplo particular, ninguno de los dos es apropiado:
La razón por la que todos están señalando esto, a pesar de que reconoces tu deseo de entender en general y tu incapacidad para encontrar un mejor ejemplo, es que los pasos secundarios equivalentes en realidad existen en muchos casos, y buscarlos es el primer paso para resolver el problema.
fuente
Siempre que lo use
try/exceptpara controlar el flujo, pregúntese:trybloque tiene éxito y cuándo falla?trybloque?trybloque arroja la excepción?trybloque cambia, ¿su flujo de control seguirá comportándose como se esperaba?Si la respuesta a una o más de estas preguntas es 'no', podría haber mucho perdón para pedir; muy probablemente de tu futuro yo.
Un ejemplo. Recientemente vi código en un proyecto más grande que se veía así:
Hablando con el programador, resultó que el flujo de control previsto era:
Esto funcionó porque
foorealizó una consulta a la base de datos y la consulta sería exitosa sixfuera un entero y arrojaría unProgrammingErrorif sixfuera una lista.Usar
try/exceptes una mala elección aquí:ProgrammingErrorno revela el problema real (quexno es un número entero), lo que dificulta ver lo que está sucediendo.ProgrammingErrorse genera durante una llamada a la base de datos, lo que desperdicia tiempo. Las cosas se pondrían realmente horribles si resulta quefooescribe algo en la base de datos antes de que arroje una excepción o altere el estado de algún otro sistema.ProgrammingErrorsolo se genera cuandoxhay una lista de enteros. Supongamos, por ejemplo, que hay un error tipográfico enfoola consulta de la base de datos. Esto también podría elevar aProgrammingError. La consecuencia es quebar(x)ahora también se llama cuandoxes un número entero. Esto podría generar excepciones crípticas o producir resultados imprevisibles.try/exceptbloque agrega un requisito a todas las implementaciones futuras defoo. Cada vez que cambiemosfoo, ahora debemos pensar en cómo maneja las listas y asegurarnos de que arroje unProgrammingErrory no, digamos, unAttributeErrorerror o ningún error.fuente
Para un significado general, puede considerar leer modismos y anti-modismos en Python: excepciones .
En su caso particular, como han dicho otros, debe usar
dict.get():fuente