长话短说:__del__
对于此目的毫无用处(以及几乎任何其他目的;您可能应该忘记它的存在)。如果您想要确定性清理,请使用上下文管理器。
据我所知,任何类实例都应该在导入代码之前被销毁,不是吗?按照声明/定义的相反顺序。
那是C++。忘了它。 Python 并不关心这一点,事实上它甚至不关心大多数需要做的事情。整个Python语言中不存在声明这样的东西,模块级变量存储在本质上是无序关联数组中。变量不存储对象,它们存储引用(即notC++ 引用,它们基本上是没有指针算术的指针)——对象位于堆上,并且不知道有关变量、绑定、语句或语句顺序的信息。
此外,当对象被垃圾收集时,并且是否完全被GC,未定义。你得到一个mostly由于引用计数,CPython 中的确定性图片是确定性的,但即使如此,它也会在出现循环时下降。结果就是__del__
可以在任何时间点调用(包括当模块的一半已经被拆除时)或根本不调用。多个对象定义__del__
互相引用也很麻烦,尽管有些 GC 努力做正确的事情。
底线是,你当时可以假设的东西很少__del__
运行,所以你不能做太多事情。您可以最后一次处理那些本应通过其他方法清理但没有清理的资源,仅此而已。经验法则:Never依靠它anything强制的。
相反,创建一个上下文管理器并通过以下方式使用它with http://docs.python.org/py3k/reference/compound_stmts.html#the-with-statement。您可以获得确定性的清理,而不必担心对象的生命周期。因为,说实话,对象生命周期和资源生命周期是两个完全不同的东西,并且只在 C++ 中纠缠在一起,因为它是进行资源管理的最佳方式在那个环境下。在 Python 中,RAII 不适用,而是这样:
with <context manager> as var:
# do something
# "context closed", whatever that means - for resources, usually cleanup
顺便说一句,您可以通过更方便地定义它上下文库 http://docs.python.org/py3k/library/contextlib.html#contextlib.contextmanager(从您的版本快速音译,可能包含错误或丑陋):
from contextlib import contextmanager
@contextmanager
def debug_wait_keypress():
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
yield
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
Your wait
方法成为自由函数。