programming oriented opp exercises español and python oop

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.

¿Puede alguien aquí explicar constructores y destructores en python? Se requiere una explicación simple; nuevo en la programación

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 ejecuta del 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:

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