__del__es un finalizador . Se llama cuando un objeto se recolecta como basura, lo que ocurre en algún momento después de que se hayan eliminado todas las referencias al objeto.
En un caso simple, esto podría ser justo después de decir del xo, si xes una variable local, después de que finalice la función. En particular, a menos que haya referencias circulares, CPython (la implementación estándar de Python) recolectará basura inmediatamente.
Sin embargo, este es un detalle de implementación de CPython. La única propiedad requerida de la recolección de basura de Python es que ocurre después de que se han eliminado todas las referencias, por lo que es posible que esto no suceda inmediatamente después y que no suceda en absoluto .
Aún más, las variables pueden vivir durante mucho tiempo por muchas razones , por ejemplo, una excepción que se propaga o la introspección del módulo pueden mantener el recuento de referencias de variables mayor que 0. Además, la variable puede ser parte del ciclo de referencias : CPython con la recolección de basura activada se interrumpe más , pero no todos, esos ciclos, e incluso entonces solo periódicamente.
Dado que no tiene garantía de que se ejecute, nunca se debe poner el código con el que debe ejecutarse; en __del__()cambio, este código pertenece a la finallycláusula del trybloque oa un administrador de contexto en una withdeclaración. Sin embargo, hay casos de uso válidos para __del__: por ejemplo, si un objeto hace Xreferencia Yy también mantiene una copia de la Yreferencia en un global cache( cache['X -> Y'] = Y), sería de buena educación X.__del__eliminar también la entrada de la caché.
Si usted sabe que el destructor proporciona (en violación de la directriz anterior) una limpieza necesaria, es posible que desee llamar directamente , ya que no hay nada especial en él como un método: x.__del__(). Obviamente, debe hacerlo solo si sabe que no le importa que lo llamen dos veces. O, como último recurso, puede redefinir este método utilizando
type(x).__del__ = my_safe_cleanup_method
__exit__en este contexto? ¿Se ejecuta después o antes__del__o en conjunto?__del__posible que los métodos no se ejecuten incluso al finalizar el programa, e incluso cuando se ejecutan al finalizar, escribir un__del__método que funcione correctamente incluso cuando el intérprete está ocupado autodestruyéndose a su alrededor requiere una codificación más cuidadosa que la que aplican muchos programadores. (La limpieza de CPython generalmente hace que los__del__métodos se ejecuten en el cierre del intérprete, pero aún hay casos en los que no es suficiente. Los subprocesos de demonio, los globales de nivel C y los objetos__del__creados en otro__del__pueden llevar a que los__del__métodos no se ejecuten).Escribí la respuesta para otra pregunta, aunque esta es una pregunta más precisa.
¿Cómo funcionan los constructores y destructores?
Aquí hay una respuesta ligeramente obstinada.
No lo use
__del__. Esto no es C ++ ni un lenguaje creado para destructores. El__del__método realmente debería desaparecer en Python 3.x, aunque estoy seguro de que alguien encontrará un caso de uso que tenga sentido. Si necesita usarlo__del__, tenga en cuenta las limitaciones básicas según http://docs.python.org/reference/datamodel.html :__del__se llama cuando el recolector de basura está recolectando los objetos, no cuando pierde la última referencia a un objeto y no cuando ejecutadel object.__del__es responsable de llamar a cualquiera__del__en una superclase, aunque no está claro si esto está en orden de resolución de método (MRO) o simplemente llamando a cada superclase.__del__medio de que el recolector de basura se rinda en detectar y limpiar cualquier enlace cíclico, como perder la última referencia a una lista enlazada. Puede obtener una lista de los objetos ignorados de gc.garbage. A veces puede usar referencias débiles para evitar el ciclo por completo. Esto se debate de vez en cuando: consulte http://mail.python.org/pipermail/python-ideas/2009-October/006194.html .__del__función puede hacer trampa, guardar una referencia a un objeto y detener la recolección de basura.__del__se ignoran.__del__complementa__new__mucho más que__init__. Esto se vuelve confuso. Consulte http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-not-the-opuesto-of- init / para obtener una explicación y trucos.__del__no es un niño "muy querido" en Python. Notará que la documentación de sys.exit () no especifica si la basura se recolecta antes de salir, y hay muchos problemas extraños. Llamar a los__del__globales provoca problemas de pedidos extraños, por ejemplo, http://bugs.python.org/issue5099 . ¿Debería__del__llamar incluso si__init__falla? Consulte http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 para ver un hilo largo.Pero en la otra mano:
__del__significa que no te olvides de llamar a una declaración de cierre. Consulte http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ para obtener un__del__punto de vista profesional . Por lo general, se trata de liberar ctypes o algún otro recurso especial.Y mi razón personal para que no me guste la
__del__función.__del__se convierte en treinta mensajes de confusión.Entonces, encuentre una razón para no usar
__del__.fuente
__del__, sino cómo llamar__del__, su respuesta es interesante.El
__del__método, se llamará cuando el objeto sea recolectado como basura. Sin embargo, tenga en cuenta que no se garantiza necesariamente que se llame. El siguiente código por sí solo no lo hará necesariamente:La razón es que
delsimplemente reduce el recuento de referencias en uno. Si algo más tiene una referencia al objeto,__del__no se llamará.Sin
__del__embargo, hay algunas advertencias sobre el uso . Por lo general, no suelen ser muy útiles. Me parece más bien que desea usar un método cercano o tal vez una declaración with .Consulte la documentación de Python sobre
__del__métodos .Otra cosa a tener en cuenta: los
__del__métodos pueden inhibir la recolección de basura si se usan en exceso. En particular, una referencia circular que tiene más de un objeto con un__del__método no obtendrá la recolección de basura. Esto se debe a que el recolector de basura no sabe a cuál llamar primero. Consulte la documentación sobre el módulo gc para obtener más información.fuente
El
__del__método (¡tenga en cuenta la ortografía!) Se llama cuando su objeto finalmente se destruye. Técnicamente hablando (en cPython) es cuando no hay más referencias a su objeto, es decir, cuando sale del alcance.Si desea eliminar su objeto y, por lo tanto, llamar al
__del__método, useque eliminará el objeto (siempre que no haya otras referencias a él).
Te sugiero que escribas una clase pequeña como esta.
E investigar en el intérprete de Python, por ejemplo
Tenga en cuenta que jython y ironpython tienen reglas diferentes en cuanto a exactamente cuándo se elimina y
__del__se llama al objeto. Sin__del__embargo, no se considera una buena práctica debido a esto y al hecho de que el objeto y su entorno pueden estar en un estado desconocido cuando se llama. Tampoco está absolutamente garantizado__del__que se llamará: el intérprete puede salir de varias formas sin eliminar todos los objetos.fuente
use del obj1parece una mala idea en la que confiar.Como se mencionó anteriormente, la
__del__funcionalidad es algo poco confiable. En los casos en que pueda parecer útil, considere utilizar los métodos__enter__y en su__exit__lugar. Esto le dará un comportamiento similar a lawith open() as f: passsintaxis utilizada para acceder a los archivos.__enter__se llama automáticamente al entrar en el ámbito dewith, mientras que__exit__se llama automáticamente al salir. Consulte esta pregunta para obtener más detalles.fuente