Je lis un code. Il existe une classe dans laquelle la méthode __del__
Est définie. J'ai compris que cette méthode est utilisée pour détruire une instance de la classe. Cependant, je ne peux pas trouver un endroit où cette méthode est utilisée. La principale raison à cela est que je ne sais pas comment cette méthode est utilisée, probablement pas comme ça: obj1.del()
. Donc, ma question est comment appeler la méthode __del__
?
__del__
Est un finaliseur. Il est appelé lorsqu'un objet est ramasse-miettes, ce qui se produit à un moment donné après que toutes les références à l'objet ont été supprimées.
Dans un cas simple, cela pourrait être juste après que vous ayez dit del x
Ou, si x
soit une variable locale, après la fin de la fonction. En particulier, à moins qu'il y ait des références circulaires, CPython (le standard Python)) sera immédiatement récupéré.
Cependant, il s’agit d’un détail d’implémentation de CPython. La seule obligatoire propriété de Python garbage collection est ce qui se passe après toutes les références ont été supprimé, donc cela pourrait ne pas nécessairement arriver juste après et pourrait ne pas arriver du tout.
Encore plus, les variables peuvent vivre longtemps beaucoup de raisons, par ex. une exception propagée ou une introspection de module peut conserver le nombre de références de variable supérieur à 0. De plus, variable peut faire partie de cycle de références - CPython avec le garbage collection activé active interrompt la plupart de ces cycles, mais pas tous. et même alors seulement périodiquement.
Puisque vous n'avez aucune garantie qu'il est exécuté, vous devriez jamais mettre le code que vous devez exécuter dans __del__()
- à la place, ce code appartient à la clause finally
de le bloc try
ou à un gestionnaire de contexte dans une instruction with
. Cependant, il existe cas d'utilisation valides pour __del__
: Par ex. si un objet X
fait référence à Y
et conserve également une copie de Y
référence dans un global cache
(cache['X -> Y'] = Y
), alors ce serait polite pour que X.__del__
supprime également l’entrée du cache.
Si vous savez que le destructeur fournit (en violation de la directive ci-dessus) un nettoyage requis, vous voudrez peut-être appelez-le directement, car il n'a rien de spécial en tant que méthode: x.__del__()
. De toute évidence, vous ne devriez le faire que si vous savez que cela ne vous dérange pas d'être appelé deux fois. Ou, en dernier recours, vous pouvez redéfinir cette méthode en utilisant
type(x).__del__ = my_safe_cleanup_method
J'ai écrit la réponse pour une autre question, bien que ce soit une question plus précise pour elle.
Comment fonctionnent les constructeurs et les destructeurs?
Voici une réponse légèrement opinionée.
N'utilisez pas __del__
. Ce n'est pas C++ ou un langage construit pour les destructeurs. La méthode __del__
Devrait vraiment être utilisée Python 3.x, bien que je sois sûr que quelqu'un trouvera un cas d'utilisation qui aura du sens. Si vous avez besoin d'utiliser __del__
, Soyez conscient des limitations de base de http://docs.python.org/reference/datamodel.html :
__del__
Est appelé lorsque le ramasse-miettes récupère les objets, pas lorsque vous perdez la dernière référence à un objet ni lorsque vous exécutez del object
.__del__
Est responsable d'appeler n'importe quel __del__
Dans une superclasse, bien qu'il ne soit pas clair s'il s'agit d'un ordre de résolution de méthode (MRO) ou s'il appelle simplement chaque superclasse.__del__
Signifie que le ramasse-miettes abandonne la détection et le nettoyage des liens cycliques, tels que la perte de la dernière référence à une liste liée. Vous pouvez obtenir une liste des objets ignorés à partir de gc.garbage. Vous pouvez parfois utiliser des références faibles pour éviter le cycle complètement. Cela fait l'objet d'un débat de temps en temps: voir http://mail.python.org/pipermail/python-ideas/2009-October/006194.html .__del__
Peut tricher en enregistrant une référence à un objet et en arrêtant le garbage collection.__del__
Sont ignorées.__del__
Complète __new__
Bien plus que __init__
. Cela devient déroutant. Voir http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-not -the-opposé-de - init / pour une explication et des pièges.__del__
N'est pas un enfant "bien aimé" en Python. Vous remarquerez que la documentation de sys.exit () ne spécifie pas si les ordures sont collectées avant de quitter, et il y a beaucoup de problèmes étranges. L'appel de __del__
Sur globals provoque des problèmes d'ordre inhabituels, par exemple, http://bugs.python.org/issue5099 . Est-ce que __del__
Doit être appelé même si le __init__
Échoue? Voir http://mail.python.org/pipermail/python-dev/2000-March/thread.html#242 pour un long fil.Mais d'autre part:
__del__
Signifie que vous n’oubliez pas d’appeler une déclaration de fermeture. Voir http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ pour un point de vue pro __del__
. Il s’agit généralement de libérer des types ou une autre ressource spéciale.Et ma raison principale de ne pas aimer la fonction __del__
.
__del__
, Il se décompose en trente messages de confusion.Alors, trouvez une raison de ne pas utiliser __del__
.
Le __del__
_ méthode, elle sera appelée lorsque l’objet est nettoyé. Notez qu'il n'est pas nécessairement garanti d'être appelé cependant. Le code suivant par lui-même ne le fera pas nécessairement:
del obj
La raison en est que del
ne décrémente que le nombre de références. Si quelque chose d'autre a une référence à l'objet, __del__
ne sera pas appelé.
Il y a quelques mises en garde concernant l'utilisation de __del__
bien que. Généralement, ils ne sont généralement pas très utiles. Il me semble que vous voulez utiliser une méthode proche ou peut-être un avec instruction .
Voir la documentation python sur __del__
méthodes .
Une autre chose à noter: __del__
méthodes peuvent empêcher le ramassage des ordures en cas de surutilisation. En particulier, une référence circulaire comportant plusieurs objets avec un __del__
La méthode ne récupère pas les ordures. En effet, le ramasse-miettes ne sait pas lequel appeler en premier. Voir la documentation sur le module gc pour plus d'informations.
Le __del__
méthode (note orthographe!) est appelée lorsque votre objet est finalement détruit. Techniquement parlant (en cPython), c’est-à-dire quand il n’ya plus de références à votre objet, c’est-à-dire quand il sort de la portée.
Si vous souhaitez supprimer votre objet et appeler ainsi le __del__
utilisation de la méthode
del obj1
qui supprimera l'objet (à condition qu'il n'y ait pas d'autres références).
Je vous suggère d'écrire une petite classe comme celle-ci
class T:
def __del__(self):
print "deleted"
Et recherchez dans l’interprète python, par exemple
>>> a = T()
>>> del a
deleted
>>> a = T()
>>> b = a
>>> del b
>>> del a
deleted
>>> def fn():
... a = T()
... print "exiting fn"
...
>>> fn()
exiting fn
deleted
>>>
Notez que jython et ironpython ont des règles différentes quant à la date exacte de suppression de l'objet et à __del__
est appelé. Ce n'est pas considéré comme une bonne pratique d'utiliser __del__
cependant à cause de cela et du fait que l'objet et son environnement peuvent être dans un état inconnu lors de son appel. Ce n'est pas absolument garanti __del__
sera appelé soit - l’interprète peut sortir de différentes manières sans supprimer tous les objets.
Comme mentionné précédemment, la fonctionnalité __del__
Est quelque peu peu fiable. Si cela vous semble utile, envisagez plutôt d'utiliser les méthodes __enter__
Et __exit__
. Cela donnera un comportement similaire à la syntaxe with open() as f: pass
utilisée pour accéder aux fichiers. __enter__
Est automatiquement appelé lors de la saisie de la portée de with
, tandis que __exit__
Est automatiquement appelé lors de sa sortie. Voir cette question pour plus de détails.