una todos matriz los lista filas eliminar elementos elemento delete python constructor garbage-collection destructor reference-counting

todos - ¿Cómo forzar la eliminación de un objeto python?



eliminar un elemento de una matriz python (4)

  1. Agregue un controlador de salida que cierre todas las barras.
  2. __del__() cuando el número de referencias a un objeto llega a 0 mientras la VM todavía está ejecutándose. Esto puede ser causado por el GC.
  3. Si __init__() genera una excepción, entonces se supone que el objeto está incompleto y __del__() no se invocará.

Tengo curiosidad acerca de los detalles de __del__ en python, cuándo y por qué se debe usar y para qué no se debe usar. Aprendí por las malas que no es realmente lo que ingenuamente se esperaría de un destructor, ya que no es lo opuesto a __new__ / __init__ .

class Foo(object): def __init__(self): self.bar = None def open(self): if self.bar != ''open'': print ''opening the bar'' self.bar = ''open'' def close(self): if self.bar != ''closed'': print ''closing the bar'' self.bar = ''close'' def __del__(self): self.close() if __name__ == ''__main__'': foo = Foo() foo.open() del foo import gc gc.collect()

Vi en la documentación que no está garantizado __del__() se solicitan métodos para objetos que aún existen cuando el intérprete sale.

  1. ¿Cómo se puede garantizar que para cualquier instancia de Foo exista cuando el intérprete se cierre, la barra esté cerrada?
  2. en el fragmento de código anterior, ¿se cierra la barra en del foo o en gc.collect() ... o ninguno? si desea un control más preciso de esos detalles (por ejemplo, la barra debe estar cerrada cuando el objeto no está referenciado), ¿cuál es la forma habitual de implementar eso?
  3. cuando __del__ es llamado ¿se garantiza que __init__ ya ha sido llamado? ¿Qué pasa si el __init__ levantado?

¿Quizás estás buscando un administrador de contexto ?

>>> class Foo(object): ... def __init__(self): ... self.bar = None ... def __enter__(self): ... if self.bar != ''open'': ... print ''opening the bar'' ... self.bar = ''open'' ... def __exit__(self, type_, value, traceback): ... if self.bar != ''closed'': ... print ''closing the bar'', type_, value, traceback ... self.bar = ''close'' ... >>> >>> with Foo() as f: ... # oh no something crashes the program ... sys.exit(0) ... opening the bar closing the bar <type ''exceptions.SystemExit''> 0 <traceback object at 0xb7720cfc>


En general, para asegurarse de que ocurra algo sin importar qué, use

from exceptions import NameError try: f = open(x) except ErrorType as e: pass # handle the error finally: try: f.close() except NameError: pass

finally bloques se ejecutarán independientemente de que haya o no un error en el bloque try , y de si hay o no un error en el manejo de errores que tiene lugar en los bloques except . Si no maneja una excepción que se genera, aún se generará después de que finally haya ejecutado el bloque finally.

La forma general de asegurarse de que un archivo esté cerrado es usar un "administrador de contexto".

http://docs.python.org/reference/datamodel.html#context-managers

with open(x) as f: # do stuff

Esto cerrará automáticamente f .

Para su pregunta n. ° 2, la bar se cierra inmediatamente cuando el recuento de referencias llega a cero, por lo tanto, en el caso de que no haya otras referencias.

Los objetos NO son creados por __init__ , son creados por __new__ .

http://docs.python.org/reference/datamodel.html#object. nuevo

Cuando haces foo = Foo() dos cosas están sucediendo realmente, primero se está creando un nuevo objeto, __new__ , luego se está inicializando, __init__ . Así que no hay forma de que puedas llamar del foo antes de que ambos pasos hayan tenido lugar. Sin embargo, si hay un error en __init__ , todavía se llamará a __del__ porque el objeto ya se creó en __new__ .

Editar: se corrige cuando se produce una eliminación si el recuento de referencias disminuye a cero.


La forma de cerrar recursos son los gestores de contexto, también conocido como la declaración with :

class Foo(object): def __init__(self): self.bar = None def __enter__(self): if self.bar != ''open'': print ''opening the bar'' self.bar = ''open'' return self # this is bound to the `as` part def close(self): if self.bar != ''closed'': print ''closing the bar'' self.bar = ''close'' def __exit__(self, *err): self.close() if __name__ == ''__main__'': with Foo() as foo: print foo, foo.bar

salida:

opening the bar <__main__.Foo object at 0x17079d0> open closing the bar

2) Los objetos de Python se eliminan cuando su recuento de referencias es 0. En su ejemplo, del foo elimina la última referencia, por lo que __del__ se llama instantáneamente. El GC no tiene parte en esto.

class Foo(object): def __del__(self): print "deling", self if __name__ == ''__main__'': import gc gc.disable() # no gc f = Foo() print "before" del f # f gets deleted right away print "after"

salida:

before deling <__main__.Foo object at 0xc49690> after

El gc no tiene nada que ver con eliminar tu y la mayoría de los otros objetos. Está ahí para limpiar cuando el recuento de referencia simple no funciona, debido a referencias propias o referencias circulares:

class Foo(object): def __init__(self, other=None): # make a circular reference self.link = other if other is not None: other.link = self def __del__(self): print "deling", self if __name__ == ''__main__'': import gc gc.disable() f = Foo(Foo()) print "before" del f # nothing gets deleted here print "after" gc.collect() print gc.garbage # The GC knows the two Foos are garbage, but won''t delete # them because they have a __del__ method print "after gc" # break up the cycle and delete the reference from gc.garbage del gc.garbage[0].link, gc.garbage[:] print "done"

salida:

before after [<__main__.Foo object at 0x22ed8d0>, <__main__.Foo object at 0x22ed950>] after gc deling <__main__.Foo object at 0x22ed950> deling <__main__.Foo object at 0x22ed8d0> done

3) Veamos:

class Foo(object): def __init__(self): raise Exception def __del__(self): print "deling", self if __name__ == ''__main__'': f = Foo()

da:

Traceback (most recent call last): File "asd.py", line 10, in <module> f = Foo() File "asd.py", line 4, in __init__ raise Exception Exception deling <__main__.Foo object at 0xa3a910>

Los objetos se crean con __new__ luego pasan a __init__ como self . Después de una excepción en __init__ , el objeto normalmente no tendrá un nombre (es decir, la parte f = no se ejecuta), por lo que su recuento de ref es 0. Esto significa que el objeto se elimina normalmente y se llama __del__ .