假设在运行时存在一个包含几个对象的程序。
程序结束时是否调用了每个对象的__del__方法?
如果是,我可以做一些这样的事情:
class Client:
__del__( self ):
disconnect_from_server()
答案 0 :(得分:7)
使用__del__
有很多potential difficulties。
通常,没有必要,或者最好自己定义它。
相反,如果您想要一个在退出或异常后自行清理的对象,请使用context manager:
根据Carl的评论:
class Client:
def __exit__(self,ext_type,exc_value,traceback):
self.disconnect_from_server()
with Client() as c:
...
原始回答:
import contextlib
class Client:
...
@contextlib.contextmanager
def make_client():
c=Client()
yield c
c.disconnect_from_server()
with make_client() as c:
...
答案 1 :(得分:5)
我的第二个概念是使用上下文管理器和with
语句而不是依赖__del__
(出于同样的原因,人们更喜欢尝试/最终使用Java中的终结器方法,加上一个:in Python,__del__
方法的存在可以使循环垃圾无法收集。
然而,鉴于目标是“退出或异常后自行清理的对象”,@ ~unutbu的实现不正确:
@contextlib.contextmanager
def make_client():
c=Client()
yield c
c.disconnect_from_server()
with make_client() as c:
...
如果在...
部分引发了异常,disconnect_from_server_
会调用而非(因为异常通过make_client
传播,在那里未被捕获,并且因此,当它在yield
)等待时终止它。
修复很简单:
@contextlib.contextmanager
def make_client():
c=Client()
try: yield c
finally: c.disconnect_from_server()
基本上,with
语句让你几乎忘记了旧的try / finally语句... 除了,当你编写上下文管理器时contextlib
,然后记住它真的很重要! - )
答案 2 :(得分:2)
考虑使用with-statement来明确清理。
使用循环引用__del__
不会被调用:
class Foo:
def __del__(self):
self.p = None
print "deleting foo"
a = Foo()
b = Foo()
a.p = b
b.p = a
什么都不打印。
答案 3 :(得分:1)
是的,Python解释器在关闭时整理,包括调用每个对象的__del__
方法(参与周期中的对象除外)。
虽然正如其他人所指出的那样,__del__
方法非常脆弱,应谨慎使用。