程序结束时__del__

Paw*_*iak 6 python

假设在运行时有一个程序包含几个对象.

程序结束时是否调用每个对象的__del__方法?

如果是,我可以举例如下:

class Client:
  __del__( self ):
    disconnect_from_server()
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 7

有许多潜在的困难与使用相关__del__.通常,没有必要,或者最好自己定义它.

相反,如果您想要一个在退出或异常后自行清理的对象,请使用上下文管理器:

根据卡尔的评论:

class Client:
    def __exit__(self,ext_type,exc_value,traceback):
        self.disconnect_from_server()

with Client() as c:
    ...
Run Code Online (Sandbox Code Playgroud)

原始答案:

import contextlib

class Client:
    ...

@contextlib.contextmanager
def make_client():
    c=Client()
    yield c
    c.disconnect_from_server()

with make_client() as c:
    ...
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 5

我的第二个概念是使用上下文管理器和with语句而不是依赖__del__(出于同样的原因,人们更喜欢尝试/最终使用Java中的终结器方法,加上一个:在Python中,__del__方法的存在可以使循环垃圾无法收集).

但是,鉴于目标是"退出或异常后自行清理的对象",@ ~unutbu的实现是正确的:

@contextlib.contextmanager
def make_client():
    c=Client()
    yield c
    c.disconnect_from_server()

with make_client() as c:
    ...
Run Code Online (Sandbox Code Playgroud)

如果在...部件中引发异常,disconnect_from_server_不会被调用(因为异常传播通过make_client,在那里未被捕获,因此在它等待时终止它yield).

修复很简单:

@contextlib.contextmanager
def make_client():
    c=Client()
    try: yield c
    finally: c.disconnect_from_server()
Run Code Online (Sandbox Code Playgroud)

从本质上讲,该with语句几乎可以让你忘记好的旧的try/finally语句... 除非你在编写上下文管理器时contextlib,然后记住它真的很重要! - )