constructor - How to force deletion of a python object? -
i curious details of __del__
in python, when , why should used , shouldn't used for. i've learned hard way not 1 naively expected destructor, in not opposite of __new__
/ __init__
.
class foo(object): def __init__(self): self.bar = none def open(self): if self.bar != 'open': print 'opening bar' self.bar = 'open' def close(self): if self.bar != 'closed': print 'closing bar' self.bar = 'close' def __del__(self): self.close() if __name__ == '__main__': foo = foo() foo.open() del foo import gc gc.collect()
i saw in documentation not guaranteed __del__()
methods called objects still exist when interpreter exits.
- how can guaranteed
foo
instances existing when interpreter exits, bar closed? - in code snippet above bar closed on
del foo
or ongc.collect()
... or neither? if want finer control of details (e.g. bar should closed when object unreferenced) usual way implement that? - when
__del__
called guaranteed__init__
has been called? if__init__
raised?
the way close resources context managers, aka with
statement:
class foo(object): def __init__(self): self.bar = none def __enter__(self): if self.bar != 'open': print 'opening bar' self.bar = 'open' return self # bound `as` part def close(self): if self.bar != 'closed': print 'closing bar' self.bar = 'close' def __exit__(self, *err): self.close() if __name__ == '__main__': foo() foo: print foo, foo.bar
output:
opening bar <__main__.foo object @ 0x17079d0> open closing bar
2) python's objects deleted when reference count 0. in example del foo
removes last reference __del__
called instantly. gc has no part in this.
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"
output:
before deling <__main__.foo object @ 0xc49690> after
the gc
has nothing deleting , other objects. it's there clean when simple reference counting not work, because of self-references or circular references:
class foo(object): def __init__(self, other=none): # make circular reference self.link = other if other 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 # gc knows 2 foos garbage, won't delete # them because have __del__ method print "after gc" # break cycle , delete reference gc.garbage del gc.garbage[0].link, gc.garbage[:] print "done"
output:
before after [<__main__.foo object @ 0x22ed8d0>, <__main__.foo object @ 0x22ed950>] after gc deling <__main__.foo object @ 0x22ed950> deling <__main__.foo object @ 0x22ed8d0> done
3) lets see:
class foo(object): def __init__(self): raise exception def __del__(self): print "deling", self if __name__ == '__main__': f = foo()
gives:
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 @ 0xa3a910>
objects created __new__
passed __init__
self
. after exception in __init__
, object typically not have name (ie f =
part isn't run) ref count 0. means object deleted , __del__
called.
Comments
Post a Comment