与其他所有 Python 实现(包括 CPython )一样,您应该这样做:通过显式管理代码中的生命周期,而不是依赖自动内存管理和.__del__
即使在 CPython 中,也有不止一种情况__del__
根本没有被调用,而且在很多情况下调用它的时间比您预期的要晚得多(例如,任何时候任何对象都陷入引用循环中,这很容易发生)。这意味着它基本上是无用的,除了可能调试生命周期问题(但有内存分析器!),如果某些代码忽略显式清理,作为最后的手段。
通过明确清理,您可以回避所有这些问题。有一个进行清理的方法,并让客户端代码在正确的时间调用它。上下文管理器可以使这在面对异常时更容易正确处理,并且更具可读性。__del__
即使引用计数“立即”调用,它通常也允许更快地清理__del__
。例如,这个:
def parse_file(path):
f = open(path)
return parse(f.read()) # file stays open during parsing
比这个 wrt 资源使用更糟糕:
def parse_file(path):
with open(path) as f:
s = f.read()
# file is closed here
return parse(s)
我还认为这样的设计更简洁,因为它不会混淆资源包装对象的生命周期和被包装资源的生命周期。有时,让该对象比资源寿命更长,甚至使其拥有新资源的所有权是有意义的。