2009-08-21 21 views
56

¿Cuál es la mejor práctica en una función definida por el usuario en Python: generar una excepción o devolver None? Por ejemplo, tengo una función que encuentra el archivo más reciente en una carpeta.Raise excepción vs. return Ninguno en las funciones de Python

def latestpdf(folder): 
    # list the files and sort them 
    try: 
     latest = files[-1] 
    except IndexError: 
     # Folder is empty. 
     return None # One possibility 
     raise FileNotFoundError() # Alternative 
    else: 
     return somefunc(latest) # In my case, somefunc parses the filename 

Otra opción es dejar la excepción y manejarlo en el código de llamada, pero me imagino que es más claro para hacer frente a una FileNotFoundError que un IndexError. ¿O es mala forma volver a plantear una excepción con un nombre diferente?

+0

similares: http://stackoverflow.com/questions/1152541/is-it-better-to-use-exception-or-return-code-in-python – codeape

+2

me inclino por lanzar una excepción por lo que me veo obligado a manejar la excepción en la función de llamada. Si olvido comprobar si el resultado es Ninguno en la función de llamada, podría tener un error latente. Si devolvió None, con suerte, la siguiente línea de la función de llamada generará un AttributeError. Sin embargo, si el valor devuelto se agrega a un diccionario y luego se invocan 100 funciones en un archivo fuente diferente, se genera un AttributeError, se divertirá buscando por qué ese valor fue None. – IceArdor

+0

En general, también evito los valores que tienen un significado especial o que tienen varias firmas para una función (podría devolver una cadena o None). – IceArdor

Respuesta

67

Es realmente una cuestión de semántica. ¿Qué significa foo = latestpdf(d)medio?

¿Es perfectamente razonable que no haya un archivo más reciente? Entonces seguro, solo devuelve None.

¿Espera encontrar siempre un archivo más reciente? Levante una excepción. Y sí, volver a plantear una excepción más adecuada está bien.

Si esto es sólo una función general que se supone que se aplican a cualquier directorio, lo haría el primero y regrese Ninguno. Si el directorio está, por ejemplo, destinado a ser un directorio de datos específico que contiene un conjunto conocido de archivos de una aplicación, me gustaría plantear una excepción.

+0

Otro punto a tener en cuenta: si se genera una excepción, se puede adjuntar un mensaje, pero no podemos hacerlo al devolver 'None'. –

1

En general, yo diría que una excepción debe ser desechado si algo catastrófico ha ocurrido que no puede ser recuperado de (es decir, sus ofertas función con algunos recursos de Internet que no se puede conectar a), y que debería volver Ninguno si su función realmente debería devolver algo, pero no sería apropiado devolver nada (es decir, "Ninguno" si su función intenta hacer coincidir una subcadena en una cadena, por ejemplo).

4

por lo general prefieren manejar excepciones internamente (es decir try/excepto dentro de la función llamada, posiblemente el retorno de una Ninguno) porque pitón se escribe de forma dinámica. En general, considero que es una cuestión de criterio de una manera u otra, pero en un lenguaje de tipos dinámicos, hay pequeños factores que inclinan la balanza a favor de no aprobar la excepción a la persona que llama: llamar

  1. nadie su función no se notifica de las excepciones que se pueden lanzar. Se convierte en una especie de forma artística saber qué tipo de excepción estás buscando (y se deben evitar los bloques genéricos excepto).
  2. if val is None es un poco más fácil que except ComplicatedCustomExceptionThatHadToBeImportedFromSomeNameSpace. En serio, odio tener que recordar escribir from django.core.exceptions import ObjectDoesNotExist en la parte superior de todos mis archivos django solo para manejar un caso de uso muy común. En un mundo estáticamente estátizado, deje que el editor lo haga por usted.

Honestamente, sin embargo, siempre es una decisión, y la situación que está describiendo, donde la función llamada recibe un error que no puede ayudar, es una excelente razón para volver a plantear una excepción que es significativa . Usted tiene la idea exacta por la derecha, pero a menos que seas una excepción va a proporcionar información más significativa en un seguimiento de la pila de

AttributeError: 'NoneType' object has no attribute 'foo' 

cuales, nueve de cada diez veces, es lo que la persona que llama si usted devuelve un no manejado Ninguno, no te molestes.

(Todo esto me hace desear que las excepciones de Python tengan los atributos cause de forma predeterminada, como en java, que le permite pasar excepciones a nuevas excepciones para que pueda volver a lanzar todo lo que desee y nunca perder la fuente original problema.)

5

Haría un par de sugerencias antes de responder a su pregunta, ya que puede responder la pregunta por usted.

  • Siempre nombre sus funciones descriptivas. latestpdf significa muy poco para cualquiera, pero revisando su función latestpdf() obtiene el último pdf. Sugeriría que lo llames getLatestPdfFromFolder(folder).

Tan pronto como lo hice quedó claro lo que debería devolver ... Si no hay un pdf, haga una excepción. Pero espere allí más ...

  • Mantenga las funciones claramente definidas. Dado que no es evidente lo que se supone que debe hacer alguien y no es (aparentemente) obvio cómo se relaciona con obtener el último pdf, le sugiero que lo retire. Esto hace que el código sea mucho más legible.

for folder in folders: 
    try: 
     latest = getLatestPdfFromFolder(folder) 
     results = somefuc(latest) 
    except IOError: pass 

Espero que esto ayude!

Cuestiones relacionadas