2009-10-01 13 views
86

¿Se considera mala forma levantar excepciones dentro de __init_? Si es así, ¿cuál es el método aceptado para arrojar un error cuando ciertas variables de clase se inicializan como None o de un tipo incorrecto?Python: ¿es mala forma levantar excepciones dentro de __init__?

+0

En C, es mala forma levantar una excepción en el destructor, pero el constructor debería estar bien. – Calyth

+4

@Calyth, quiere decir C++ - no hay constructores o destructores en C. –

+2

... o excepciones, para el caso. –

Respuesta

111

Aumentando las excepciones dentro de __init__() está absolutamente bien. No hay otra manera de indicar una condición de error dentro de un constructor, y hay muchos cientos de ejemplos en la biblioteca estándar donde crear un objeto puede generar una excepción.

La clase de error a plantear, por supuesto, depende de usted. ValueError es mejor si al constructor se le pasó un parámetro no válido.

+14

Las excepciones más utilizadas en el constructor son 'ValueError' y' TypeError'. –

+0

Solo señalando que '__init__' no es el constructor, es el inicializador. Es posible que desee editar la línea * No hay otra buena manera de indicar una condición de error dentro de un constructor, .. * – Haris

3

Creo que es el caso perfecto para la excepción incorporada ValueError.

5

La librería estándar dice:

>>> f = file("notexisting.txt") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 2] No such file or directory: 'notexisting.txt' 

también que no veo ninguna razón por la que debe ser considerado de mala educación.

11

No veo ningún motivo por el que deba estar en mal estado.

Por el contrario, una de las excepciones de las cosas conocidas para hacerlo bien, a diferencia de devolver los códigos de error, es que los códigos de error generalmente no pueden ser devueltos por los constructores. Entonces, al menos en idiomas como C++, elevar excepciones es la única forma de señalar errores.

2

Estoy de acuerdo con todo lo anterior.

Realmente no hay otra manera de señalar que algo salió mal en la inicialización de un objeto que no sea el de generar una excepción.

En la mayoría de las clases de programas donde el estado de una clase depende totalmente de las entradas a esa clase, podemos esperar que se genere algún tipo de ValueError o TypeError.

Las clases con efectos secundarios (por ejemplo, una red o gráficos) pueden generar un error en init si (por ejemplo) el dispositivo de red no está disponible o no se puede escribir el objeto canvas. Esto me parece sensato porque a menudo quiere saber sobre las condiciones de falla lo antes posible.

18

Es cierto que la única forma correcta de indicar un error en un constructor es presentar una excepción. Es por eso que en C++ y en otros lenguajes orientados a objetos que han sido diseñados teniendo en cuenta la seguridad de excepciones, no se llama al destructor si se lanza una excepción en el constructor de un objeto (lo que significa que la inicialización del objeto está incompleta). Este no suele ser el caso en los lenguajes de scripting, como Python. Por ejemplo, el siguiente código lanza una AttributeError si Socket.connect() falla:

class NetworkInterface: 
    def __init__(self, address) 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.socket.connect(address) 
     self.stream = self.socket.makefile() 

    def __del__(self) 
     self.stream.close() 
     self.socket.close() 

La razón es que el destructor del objeto incompleto es llamado después de que el intento de conexión ha fallado, antes de que el atributo de flujo se ha inicializado . No deberías evitar arrojar excepciones de los constructores, solo digo que es difícil escribir un código completamente seguro en Python. Algunos desarrolladores de Python evitan usar destructores por completo, pero eso es una cuestión de otro debate.

+0

Esta respuesta es realmente útil. No se trata solo de hablar sobre la "luz verde", sino que menciona un ejemplo con el "destructor". – lpapp

2

En algunos casos, evitar los errores de init es inevitable, pero hacer demasiado trabajo en init es un mal estilo. Debería considerar hacer una fábrica o una pseudo fábrica: un método de clase simple que devuelve un objeto configurado.

Cuestiones relacionadas