opp - python object oriented programming pdf
¿Cuál es el método__del__, cómo llamarlo? (4)
Estoy leyendo un código. Hay una clase en la que se __del__
método __del__
. Descubrí que este método se usa para destruir una instancia de la clase. Sin embargo, no puedo encontrar un lugar donde se use este método. La razón principal de esto es que no sé cómo se usa este método, probablemente no así: obj1.del()
. Entonces, mi pregunta es cómo llamar al método __del__
? Gracias por cualquier ayuda.
El método __del__
, se llamará cuando el objeto sea basura recolectada. Tenga en cuenta que no es necesariamente garantizado para ser llamado sin embargo. El siguiente código por sí solo no necesariamente lo hará:
del obj
La razón es que del
solo disminuye la cuenta de referencia en uno. Si algo más tiene una referencia al objeto, __del__
no se llamará.
Sin embargo, hay algunas advertencias sobre el uso de __del__
. En general, generalmente no son muy útiles. Me parece más como si quisieras usar un método cercano o tal vez un enunciado .
Consulte la documentación de python en los métodos __del__
.
Otra cosa a tener en cuenta: los métodos __del__
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 método __del__
no obtendrá basura recolectada. Esto se debe a que el recolector de basura no sabe a cuál llamar primero. Consulte la documentación en el módulo gc para más información.
Escribí la respuesta para otra pregunta, aunque esta es una pregunta más precisa para ello.
Aquí hay una respuesta ligeramente obstinada.
No use __del__
. Esto no es C ++ o un lenguaje creado para destructores. El método __del__
realmente debería desaparecer en Python 3.x, aunque estoy seguro de que alguien encontrará un caso de uso que tenga sentido. Si necesita usar __del__
, tenga en cuenta las limitaciones básicas por http://docs.python.org/reference/datamodel.html :
-
__del__
se__del__
cuando el recolector de basura está recolectando los objetos, no cuando se pierde la última referencia a un objeto y no cuando se ejecutadel object
. -
__del__
es responsable de llamar a cualquier__del__
en una superclase, aunque no está claro si esto es en orden de resolución de método (MRO) o simplemente llamando a cada superclase. - Tener un
__del__
significa que el recolector de basura se da por vencido en la detección y limpieza de cualquier enlace cíclico, como perder la última referencia a una lista vinculada. 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: ver http://mail.python.org/pipermail/python-ideas/2009-October/006194.html . - La función
__del__
puede hacer trampa, guardar una referencia a un objeto y detener la recolección de basura. - Las excepciones explícitamente planteadas en
__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-opposite-of-init/ para obtener una explicación y sugerencias. -
__del__
no es un niño "muy querido" en Python. Notará que la documentación sys.exit () no especifica si se recoge basura antes de salir, y hay muchos problemas extraños. Llamar a__del__
en globales causa problemas de ordenamiento extraño, por ejemplo, http://bugs.python.org/issue5099 . ¿Debe__del__
llamado incluso si__init__
falla? Ver http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423 para un hilo largo.
Pero en la otra mano:
-
__del__
significa que no te olvides de llamar a una declaración cerrada. Consulte http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ para obtener un__del__
vista pro__del__
. Por lo general, se trata de liberar ctypes o algún otro recurso especial.
Y mi razón personal para que no me __del__
función __del__
.
- Cada vez que alguien menciona
__del__
se convierte en treinta mensajes de confusión. - Rompe estos elementos en el Zen de Python:
- Simple es mejor que complicado.
- Los casos especiales no son lo suficientemente especiales como para romper las reglas.
- Los errores nunca deberían pasar silenciosamente.
- En vista de la ambigüedad, rechace la tentación de adivinar.
- Debería haber una, y preferiblemente solo una, forma obvia de hacerlo.
- Si la implementación es difícil de explicar, es una mala idea.
Entonces, encuentra una razón para no usar __del__
.
Se __del__
método __del__
(¡ __del__
ortografía!) Cuando su objeto finalmente se destruye. Técnicamente hablando (en cPython) es cuando ya no hay más referencias a su objeto, es decir, cuando sale del alcance.
Si desea eliminar su objeto y, por lo tanto, llame al método __del__
use
del obj1
que eliminará el objeto (siempre que no haya otras referencias).
Te sugiero que escribas una clase pequeña como esta
class T:
def __del__(self):
print "deleted"
E investigar en el intérprete de Python, por ejemplo
>>> 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
>>>
Tenga en cuenta que jython y ironpython tienen reglas diferentes sobre exactamente cuándo se borra el objeto y se llama a __del__
. __del__
embargo, no se considera una buena práctica usar __del__
debido a esto y al hecho de que el objeto y su entorno pueden estar en un estado desconocido cuando se lo llama. No está absolutamente garantizado que __del__
sea llamado tampoco - el intérprete puede salir de varias maneras sin borrar todos los objetos.
__del__
es un destructor . Se invoca cuando un objeto se recolecta basura, lo que sucede 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 que del x
o, si x
es una variable local, después de que la función finaliza. En particular, a menos que haya referencias circulares, CPython (la implementación estándar de Python) recogerá basura inmediatamente.
Sin embargo, este es el 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 hayan eliminado todas las referencias, por lo que es posible que esto no ocurra inmediatamente y que no ocurra .
Aún más, las variables pueden vivir por un largo tiempo por muchas razones , por ejemplo, una excepción de propagación o la introspección del módulo puede mantener un conteo de referencia variable mayor a 0. Además, la variable puede ser parte del ciclo de referencias . CPython con la recolección de basura activada rompe más , pero no todos, tales ciclos, e incluso entonces solo periódicamente.
Como no tiene garantía de que se ejecute, nunca se debe ejecutar el código que necesita ejecutar en __del__()
; en cambio, este código pertenece a la cláusula finally
del bloque try
o a un gestor de contexto en una instrucción with
. Sin embargo, hay casos de uso válidos para __del__
: por ejemplo, si un objeto X
referencia a Y
y también guarda una copia de referencia Y
en un cache
global ( cache[''X -> Y''] = Y
), entonces sería educado para X.__del__
para eliminar también la entrada de caché.
Si sabe que el destructor proporciona (en violación de la guía anterior) una limpieza requerida, puede llamar directamente , ya que no tiene nada de especial como 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 usando
type(x).__del__ = my_safe_cleanup_method