2008-11-01 16 views
317

Me preguntaba acerca de las mejores prácticas para indicar combinaciones de argumentos no válidos en Python. Me he encontrado con algunas situaciones donde se tiene una función de este modo:¿Qué excepción debo plantear en las combinaciones de argumentos malos/ilegales en Python?

def import_to_orm(name, save=False, recurse=False): 
    """ 
    :param name: Name of some external entity to import. 
    :param save: Save the ORM object before returning. 
    :param recurse: Attempt to import associated objects as well. Because you 
     need the original object to have a key to relate to, save must be 
     `True` for recurse to be `True`. 
    :raise BadValueError: If `recurse and not save`. 
    :return: The ORM object. 
    """ 
    pass 

La única molestia con esto es que cada paquete tiene su propia, por lo general ligeramente diferentes BadValueError. Sé que en Java existe java.lang.IllegalArgumentException - ¿Está bien entendido que todos crearán sus propios BadValueError s en Python o hay otro método preferido?

Respuesta

348

me acaba de levantar ValueError, a menos que necesite una excepción más específica ..

def import_to_orm(name, save=False, recurse=False): 
    if recurse and not save: 
     raise ValueError("save must be True if recurse is True") 

Realmente no hay razón para hacer class BadValueError(ValueError):pass - la clase personalizada es idéntica en uso a ValueError, ¿por qué no usar eso?

+0

Estoy de acuerdo: casi siempre uso ValueError para cosas como esta, también. – mipadi

+39

> "¿por qué no usar eso?" - Especificidad. Quizás quiera capturar en alguna capa externa "MyValueError", pero no en ninguno/todos "ValueError". –

+6

Sí, así que parte de la cuestión de la especificidad es dónde más se levanta ValueError. Si a la función llamada le gustan sus argumentos pero llama a math.sqrt (-1) internamente, una persona que llama puede estar atrapando ValueError. Espere que * sus * argumentos sean inapropiados. Tal vez solo verifique el mensaje en este caso ... – cdleary

8

He visto casi todo el built-in ValueError utilizado en esta situación.

65

que heredaría de ValueError

class IllegalArgumentError(ValueError): 
    pass 

A veces es mejor crear sus propias excepciones, pero heredar de un sistema incorporado en uno, que es lo más cercano a lo que quiere como sea posible.

Si necesita detectar ese error específico, es útil tener un nombre.

+13

Deja de escribir clases y excepciones personalizadas - http://pyvideo.org/video/880/stop-writing-classes –

+21

@HamishGrubijan ese video es terrible. Cuando alguien sugirió un buen uso de una clase, simplemente dijo "No uses clases". Brillante. Las clases son buenas [Pero no crea en mi palabra] (http://lucumr.pocoo.org/2013/2/13/moar-classes/). –

+5

@RobertGrant No, no lo entiendes. Ese video no trata realmente sobre literalmente "no usar clases". Se trata de no complicar demasiado las cosas. – RayLuo

2

no estoy seguro estoy de acuerdo con la herencia de ValueError - mi interpretación de la documentación es que ValueError es solamente supuesta para ser criados por órdenes internas ... heredando de o elevándola a sí mismo parece incorrecta.

elevada cuando una operación incorporada o función recibe un argumento que tiene el tipo correcto pero un inapropiado valor, y la situación no es descrito por una excepción más precisa como IndexError.

- ValueError documentation

+4

Operación incorporada * Función OR * – dbr

+0

Comparar http://www.google.com/codesearch?q=lang:python+class\+\w*Error\(([^E]\w*|E [^ x] \ w *) \): con http: //www.google.com/codesearch? q = lang: python + clase \ + \ w * Error \ (Excepción \): –

+0

@dbr: Sí, yo piensan que significan "(función o función incorporada)", no "(operación incorporada) o función". Creo que lo habrían contrastado diciendo "definido por el usuario" en el segundo caso. – cdleary

0

Acepte la sugerencia de Markus de ejecutar su propia excepción, pero el texto de la excepción debe aclarar que el problema está en la lista de argumentos, no en los valores de los argumentos individuales. Me propongo:

class BadCallError(ValueError): 
    pass 

Se utiliza cuando los argumentos de palabras clave faltan que se requiere para la llamada específica, o valores de los argumentos son válidos de forma individual, pero incompatibles entre sí. ValueError seguiría siendo correcto cuando un argumento específico es correcto pero fuera de rango.

¿No debería ser esta una excepción estándar en Python?

En general, me gustaría que el estilo de Python fuera un poco más nítido para distinguir las entradas incorrectas de una función (falla del que llama) de los malos resultados dentro de la función (mi culpa). Por lo tanto, también podría haber un error BadArgumentError para distinguir los errores de valor en los argumentos de los errores de valor en los locales.

Cuestiones relacionadas