Il y a une différence entre un constructeur en C++ et une méthode __init__
en Python. En C++, la tâche d'un constructeur est de construire un objet. En cas d'échec, aucun destructeur n'est appelé. Par conséquent, si des ressources ont été acquises avant la levée d'une exception , le nettoyage doit être effectué avant de quitter le constructeur. Ainsi, certains préfèrent la construction à deux phases avec la plupart de la construction faite en dehors du constructeur (pouah).
Python a une construction à deux phases beaucoup plus propre (construction, puis initialize). Cependant, beaucoup de personnes confondent une méthode __init__
(initialiseur) avec un constructeur. Le constructeur actuel en Python est appelé __new__
. Contrairement à C++, il ne prend pas d'instance, mais renvoie une instance. La tâche de __init__
consiste à initialiser l'instance créée. Si une exception est levée dans __init__
, le destructeur __del__
(le cas échéant) sera appelé comme prévu, car l'objet a déjà été créé (même s'il n'a pas été correctement initialisé) au moment où __init__
a été appelé.
répondre à votre question:
En Python, si le code dans votre "constructeur" échoue, l'objet se termine par ne pas être défini.
Ce n'est pas exactement vrai. Si __init__
déclenche une exception, l'objet est créé mais pas initialisé correctement (par exemple, certains attributs ne sont pas ). Mais au moment où il est levé, vous n'avez probablement aucune référence à cet objet, donc le fait que les attributs ne sont pas attribués n'a pas d'importance. Seul le destructeur (le cas échéant) doit vérifier si les attributs existent réellement.
Quelle est la meilleure façon de procéder?
En Python, initialisez les objets dans __init__
et ne vous inquiétez pas des exceptions. En C++, utilisez RAII.
Mise à jour [sur la gestion des ressources]:
Dans les langues les déchets collectés, si vous faites affaire avec des ressources, en particulier celles limitées telles que les connexions de base de données, il est préférable de ne pas les libérer dans le destructor. Ceci est parce que les objets sont détruits d'une manière non déterministe, et si vous arrive d'avoir une boucle de références (qui est pas toujours facile de dire), et au moins l'un des objets dans la boucle a un destructor défini, ils ne seront jamais détruits. Les langues collectées par les ordures ont d'autres moyens de gérer les ressources. En Python, c'est un with statement.
ok, je me souviens que, je Je suis encore nouveau ici et je veux donner du crédit aux gens qui passent leur temps précieux, essayant de répondre à mes questions, je l'apprécie vraiment! – Tom
Cette question vient loin de Python et même de l'explication de tout ce qui concerne RAII ou pourquoi pouvons-nous/ne pouvons pas faire des opérations dans un constructeur qui peut déclencher une exception? – lispmachine
@Neil Butterworth: ce n'est pas vraiment important puisque vous pouvez accepter une autre meilleure réponse plus tard. –