Est-il considéré comme une mauvaise forme de soulever des exceptions à l'intérieur __init__
? Si tel est le cas, quelle est la méthode acceptée pour lancer une erreur lorsque certaines variables de classe sont initialisées comme None
ou d'un type incorrect?
128
Réponses:
Soulever des exceptions à l'intérieur
__init__()
est absolument parfait. Il n'y a pas d'autre bon moyen d'indiquer une condition d'erreur dans un constructeur, et il existe plusieurs centaines d'exemples dans la bibliothèque standard où la construction d'un objet peut déclencher une exception.La classe d'erreur à élever, bien sûr, dépend de vous.
ValueError
est préférable si le constructeur a reçu un paramètre non valide.la source
ValueError
etTypeError
.__init__
n'est pas le constructeur, c'est l'initiateur. Vous voudrez peut-être modifier la ligne. Il n'y a pas d'autre bon moyen d'indiquer une condition d'erreur dans un constructeur, ..Il est vrai que la seule manière correcte d'indiquer une erreur dans un constructeur est de lever une exception. C'est pourquoi en C ++ et dans d'autres langages orientés objet qui ont été conçus avec la sécurité des exceptions à l'esprit, le destructeur n'est pas appelé si une exception est levée dans le constructeur d'un objet (ce qui signifie que l'initialisation de l'objet est incomplète). Ce n'est souvent pas le cas dans les langages de script, tels que Python. Par exemple, le code suivant lève une AttributeError si socket.connect () échoue:
La raison en est que le destructeur de l'objet incomplet est appelé après l'échec de la tentative de connexion, avant que l'attribut stream n'ait été initialisé. Vous ne devriez pas éviter de lancer des exceptions de la part des constructeurs, je dis simplement qu'il est difficile d'écrire du code entièrement sécurisé en Python. Certains développeurs Python évitent complètement d'utiliser des destructeurs, mais c'est un autre débat.
la source
__del__
car il est mal écrit. Vous auriez exactement le même problème si vous le faisiezthis->p_socket->close()
dans un destructeur en C ++. En C ++, vous ne feriez pas cela - vous laisseriez l'objet membre se détruire. Faites de même en python.Je ne vois aucune raison pour que ce soit une mauvaise forme.
Au contraire, l'une des choses que les exceptions sont connues pour bien faire, par opposition au renvoi de codes d'erreur, est que les codes d'erreur ne peuvent généralement pas être retournés par les constructeurs. Donc, au moins dans des langages comme C ++, lever des exceptions est le seul moyen de signaler les erreurs.
la source
La bibliothèque standard dit:
De plus, je ne vois pas vraiment pourquoi cela devrait être considéré comme une mauvaise forme.
la source
Je devrais penser que c'est le cas parfait pour l'
ValueError
exception intégrée .la source
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é lors de l'initialisation d'un objet autre que de lever une exception.
Dans la plupart des classes de programmes où l'état d'une classe dépend entièrement des entrées de cette classe, nous pouvons nous attendre à ce qu'une sorte de ValueError ou TypeError soit déclenchée.
Les classes avec des effets secondaires (par exemple, celles qui font du réseautage ou des graphiques) peuvent générer une erreur dans init si (par exemple) le périphérique réseau n'est pas disponible ou l'objet canevas ne peut pas être écrit. Cela me semble judicieux car vous souhaitez souvent connaître les conditions de défaillance le plus rapidement possible.
la source
Relever des erreurs depuis init est inévitable dans certains cas, mais faire trop de travail dans init est un mauvais style. Vous devriez envisager de créer une fabrique ou une pseudo-fabrique - une méthode de classe simple qui renvoie un objet configuré.
la source