¿Debo probar que if
algo es válido o simplemente try
hacerlo 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 try
lugar de un if
como 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 mylist
prueba si el índice es un elemento de mylist, no un índice posible. Te gustaría en suif index < len(mylist)
lugar.if/else
quetry/catch
En 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
try
yexcept
directamente en lugar de dentro de unif
guardia 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
isdir
ymkdir
, 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:
break
no 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 / else
ytry / except
puede 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 aif
vs.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 (try
puede 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
try
es reconocer que puede pasar un error, que es lo opuesto a que pase en silencio. El usoexcept
está 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
pass
en unexcept
bloque, 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/except
para controlar el flujo, pregúntese:try
bloque tiene éxito y cuándo falla?try
bloque?try
bloque arroja la excepción?try
bloque 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
foo
realizó una consulta a la base de datos y la consulta sería exitosa six
fuera un entero y arrojaría unProgrammingError
if six
fuera una lista.Usar
try/except
es una mala elección aquí:ProgrammingError
no revela el problema real (quex
no es un número entero), lo que dificulta ver lo que está sucediendo.ProgrammingError
se genera durante una llamada a la base de datos, lo que desperdicia tiempo. Las cosas se pondrían realmente horribles si resulta quefoo
escribe algo en la base de datos antes de que arroje una excepción o altere el estado de algún otro sistema.ProgrammingError
solo se genera cuandox
hay una lista de enteros. Supongamos, por ejemplo, que hay un error tipográfico enfoo
la consulta de la base de datos. Esto también podría elevar aProgrammingError
. La consecuencia es quebar(x)
ahora también se llama cuandox
es un número entero. Esto podría generar excepciones crípticas o producir resultados imprevisibles.try/except
bloque 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 unProgrammingError
y no, digamos, unAttributeError
error 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