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
fooinstances existing when interpreter exits, bar closed? - in code snippet above bar closed on
del fooor 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