Python: Est-ce une mauvaise forme de lever des exceptions dans __init__?
Est-il considéré comme une mauvaise forme de lever des exceptions au sein de __init__
? Si oui, alors qu'est-ce que la méthode de jeter une erreur lors de certaines variables de classe sont initialisés comme None
ou d'un type incorrect?
- En C, il est mal vu de soulever une exception dans le destructeur, mais le constructeur devrait être bon.
- tu veux dire C++ -- il n'y a pas de constructeurs ou destructeurs dans C.
- ...ou des exceptions, pour cette question.
- lol, merci de supprimer cette absurde de la déclaration faite par un innocent faute de frappe 😉
- oui. C++. FML. Et je ne pouvais pas éditer ce commentaire. Si l'internet est le document de mon idiotie 😉
Vous devez vous connecter pour publier un commentaire.
Soulever des exceptions dans
__init__()
est absolument parfait. Il n'y a pas d'autre bonne façon d'indiquer une condition d'erreur au sein d'un constructeur, et il y a plusieurs centaines d'exemples dans la bibliothèque standard, où la construction d'un objet peut déclencher une exception.La classe d'erreur de relance, bien sûr, est à vous.
ValueError
est meilleur si le constructeur a passé un paramètre non valide.ValueError
etTypeError
.__init__
n'est pas le constructeur, son la intializer. Vous pouvez modifier la ligne Il n'y a pas d'autre bonne façon d'indiquer une condition d'erreur au sein d'un constructeur,..Il est vrai que la seule manière pour indiquer une erreur dans un constructeur est le déclenchement d'une exception. C'est pourquoi, en C++ et autres langages orientés objet, qui ont été conçus à l'exception de la sécurité à l'esprit, le destructeur n'est pas appelée si une exception est levée dans le constructeur d'un objet (ce qui signifie que l'initialisation de l'objet est incomplet). Ce n'est pas souvent le cas dans les langages de script comme Python. Par exemple, le code suivant génère une AttributeError si le socket.connect() échoue:
La raison en est que le destructeur de l'incomplétude de l'objet est appelé après la tentative de connexion a échoué, avant que le flux de l'attribut a été initialisé. Vous ne devriez pas éviter de jeter des exceptions de constructeurs, je dis juste que c'est difficile d'écrire entièrement exception coffre-fort à code en Python. Certains développeurs Python éviter d'utiliser des destructeurs, mais c'est une question d'un autre débat.
__del__
parce qu'il est mal écrit. Vous auriez exactement le même problème si vous n'avezthis->p_socket->close()
dans un destructeur en C++. En C++, vous ne le ferais pas, - vous laisserais le membre objet de détruire lui-même. Faire la même chose en python.Je ne vois pas de raison qu'elle devrait être en mauvaise forme.
Au contraire, l'une des choses les exceptions sont connus pour faire bien, plutôt que de retourner les codes d'erreur, c'est que les codes d'erreur généralement ne peut pas être retournés par les constructeurs. Ainsi, au moins dans des langages comme le C++, le déclenchement d'exceptions est la seule façon pour les erreurs de signal.
De la bibliothèque standard dit:
Aussi je ne vois vraiment aucune raison pourquoi il devrait être considéré comme une mauvaise forme.
Je pense que c'est le cas parfait pour les haut-
ValueError
exception.Je suis d'accord avec tout ce qui précède.
Il n'y a vraiment pas d'autre moyen de signaler que quelque chose s'est mal passé dans l'initialisation d'un objet autre que de lever une exception.
Dans la plupart des programmes des classes où l'état d'une classe est un proche entièrement à charge sur les entrées de la classe que nous pourrions nous attendre à une sorte de ValueError ou TypeError à être soulevée.
Classes avec des effets secondaires (par exemple, celui qui n'réseau ou de graphiques) peut générer une erreur dans init (par exemple) si le périphérique réseau n'est pas disponible, ou sur la toile objet ne peut pas être écrite. Cela semble raisonnable pour moi, parce que souvent vous voulez savoir sur les conditions de panne dès que possible.
La levée des erreurs d'initialisation est inévitable dans certains cas, mais de faire trop de travail dans l'init est un mauvais style. Vous devriez envisager de faire une usine ou d'un pseudo-usine - une simple classmethod que les retours programmés de l'objet.