如何强制删除一个python对象? [英] How to force deletion of a python object?
问题描述
我很好奇在python中的 __ del __
的细节,当和为什么它应该使用,它不应该使用。我学到了一个困难的方式,它不是真的像一个天真的预期从一个析构函数,因为它不是 __ new __
/ __ init __
。
I am curious about the details of __del__
in python, when and why it should be used and what it shouldn't be used for. I've learned the hard way that it is not really like what one would naively expected from a destructor, in that it is not the opposite of __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()
我在文档中看到,它不是保证 __ del __()
解释器退出。
I saw in the documentation that it is not guaranteed __del__()
methods are called for objects that still exist when the interpreter exits.
- 如何保证对于解释器退出时存在的任何
Foo
,该栏在以下代码段中是否关闭? c> del foo 或gc.collect()
...或者两者都不?如果你想要更细微的控制这些细节(例如,当对象未被引用时,应该关闭这个bar)。 -
__ del __
被调用是否保证__ init __
已被调用?如果__ init __
引发?
- how can it be guaranteed that for any
Foo
instances existing when the interpreter exits, the bar is closed? - in the code snippet above does the bar get closed on
del foo
or ongc.collect()
... or neither? if you want finer control of those details (e.g. the bar should be closed when the object is unreferenced) what is the usual way to implement that? - when
__del__
is called is it guaranteed that__init__
has already been called? what about if the__init__
raised?
推荐答案
关闭资源的方法是上下文管理器,也就是与语句:
The way to close resources are context managers, aka the with
statement:
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
输出:
opening the bar
<__main__.Foo object at 0x17079d0> open
closing the bar
Python的对象在引用计数为0时被删除。在你的例子中, del foo
删除最后一个引用,所以 __ del __
立即叫。这个GC没有部分。
2) Python's objects get deleted when their reference count is 0. In your example the del foo
removes the last reference so __del__
is called instantly. The 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"
之前的
del f#f被删除
print
输出:
output:
before
deling <__main__.Foo object at 0xc49690>
after
gc
与删除您的和大多数其他对象无关。
The gc
has nothing to do with deleting your and most other objects. It's there to clean up when simple reference counting does not work, because of self-references or circular references:
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"
输出:
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) Lets see:
class Foo(object):
def __init__(self):
raise Exception
def __del__(self):
print "deling", self
if __name__ == '__main__':
f = Foo()
提供:
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>
使用 __ new __
创建对象,然后传递给 __ init __
为 self
。在 __ init __
中的异常之后,对象通常不会有一个名称(即 f =
),所以它们的引用计数为0.这意味着对象被正常删除,并且调用 __ del __
。
Objects are created with __new__
then passed to __init__
as self
. After a exception in __init__
, the object will typically not have a name (ie the f =
part isn't run) so their ref count is 0. This means that the object is deleted normally and __del__
is called.
这篇关于如何强制删除一个python对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!