Python 在pypy清理

Python 在pypy清理,python,pypy,Python,Pypy,我一直在寻找清理python中对象的方法。 我目前正在使用pypy 我找到了一个网页和一个例子 首先是一个基本的例子: class FooType(object): def __init__(self, id): self.id = id print self.id, 'born' def __del__(self): print self.id, 'died' ft = FooType(1) 应打印: 1出生 1人死亡 但

我一直在寻找清理python中对象的方法。 我目前正在使用pypy

我找到了一个网页和一个例子

首先是一个基本的例子:

class FooType(object):
    def __init__(self, id):
        self.id = id
        print self.id, 'born'

    def __del__(self):
        print self.id, 'died'


ft = FooType(1)
应打印:

1出生 1人死亡

但它只是印刷品 1出生

所以我的问题是:如何在PyPy中清理任何东西?

当您需要在特定时间运行“清理”时,请使用

当您需要在特定时间确保运行“清理”时,请使用

在包括CPython在内的所有其他Python实现中都应该采用同样的方法:在代码中显式地管理生命周期,而不是依赖于自动内存管理和
\uu del\uu

即使在CPython中,也有不止一种情况下,
\uu del\uu
根本不被称为,还有相当多的情况下,调用它的时间比您预期的要晚得多(例如,任何对象在引用循环中被捕获的任何时候,这都很容易发生)。这意味着它基本上是无用的,除了调试生命周期问题(但有内存分析器!)以及作为最后手段,如果某些代码忽略显式清理

通过明确说明清理,您可以避开所有这些问题。拥有一个执行清理的方法,并让客户端代码在正确的时间调用它。上下文管理器可以使这一点在遇到异常时更容易正确,并且更具可读性。即使引用计数“立即”调用
\uuu del\uuu
,它通常也允许比
\uu del\uuu
更快地进行清理。例如,这:

def parse_file(path):
    f = open(path)
    return parse(f.read()) # file stays open during parsing
比这个水资源利用率更糟糕:

def parse_file(path):
    with open(path) as f:
        s = f.read()
    # file is closed here
    return parse(s)
我还认为这样的设计更干净,因为它不会混淆资源包装器对象的生存期和包装资源的生存期。有时,让该对象比资源寿命长,甚至让它拥有一个新资源是有意义的。

在其他所有Python实现中,包括CPython中,都应该采用同样的方法:在代码中显式管理生命周期,而不是依赖自动内存管理和
\u del\u

即使在CPython中,也有不止一种情况下,
\uu del\uu
根本不被称为,还有相当多的情况下,调用它的时间比您预期的要晚得多(例如,任何对象在引用循环中被捕获的任何时候,这都很容易发生)。这意味着它基本上是无用的,除了调试生命周期问题(但有内存分析器!)以及作为最后手段,如果某些代码忽略显式清理

通过明确说明清理,您可以避开所有这些问题。拥有一个执行清理的方法,并让客户端代码在正确的时间调用它。上下文管理器可以使这一点在遇到异常时更容易正确,并且更具可读性。即使引用计数“立即”调用
\uuu del\uuu
,它通常也允许比
\uu del\uuu
更快地进行清理。例如,这:

def parse_file(path):
    f = open(path)
    return parse(f.read()) # file stays open during parsing
比这个水资源利用率更糟糕:

def parse_file(path):
    with open(path) as f:
        s = f.read()
    # file is closed here
    return parse(s)

我还认为这样的设计更干净,因为它不会混淆资源包装器对象的生存期和包装资源的生存期。有时,让该对象比资源寿命长,甚至让它拥有一个新资源是有意义的。

在您的示例中,不会调用
\uu del\uu
,但这只是因为您编写的测试程序立即完成。PyPy保证在对象不再可访问后的一段时间调用
\uuuu del\uuu
,但只要程序继续执行。因此,如果您在无限循环中执行
ft=FooType(1)
,它也会在一段时间后打印
died


正如其他答案所解释的,CPython并不能真正保证任何事情,但在简单的情况下(例如,没有参考循环),它会立即可靠地调用
\uuuu del\uuu
。不过,关键是您不应该严格依赖于此。

在您的示例中,
\uu del\uu
没有被调用,但这只是因为您编写的测试程序立即完成。PyPy保证在对象不再可访问后的一段时间调用
\uuuu del\uuu
,但只要程序继续执行。因此,如果您在无限循环中执行
ft=FooType(1)
,它也会在一段时间后打印
died


正如其他答案所解释的,CPython并不能真正保证任何事情,但在简单的情况下(例如,没有参考循环),它会立即可靠地调用
\uuuu del\uuu
。不过,关键是你不应该严格依赖它。

Python不做RAII;PyPy使用垃圾收集,并且析构函数永远不能保证运行。取决于垃圾收集。。。解释器可能不会释放对象,直到它需要更多内存。CPython使用引用计数,并在没有更多引用时立即释放它。您是否调用
del ft
?@Hidde,因为
del
只删除引用,而不是调用
\u del\u
或强制GC,这通常无关紧要;PyPy使用垃圾收集,并且析构函数永远不能保证运行。取决于垃圾收集。。。解释器可能不会释放对象,直到它需要更多内存。CPython使用引用计数,并在没有更多引用时立即释放引用。您是否调用
del ft
?@Hidde as
del
仅删除引用,而不是调用
\u del\u
或强制执行GC,这通常无关紧要。