3

我正在试验 Python 的with语句,我发现在下面的代码清单中,我的__init__方法被调用了两次,而我的__exit__方法被调用了一次。这大概意味着如果这段代码做了任何有用的事情,就会发生资源泄漏。

class MyResource:
    def __enter__(self):
        print 'Entering MyResource'
        return MyResource()

    def __exit__(self, exc_type, exc_value, traceback):
        print 'Cleaning up MyResource'

    def __init__(self):
        print 'Constructing MyResource'

    def some_function(self):
        print 'Some function'

def main():
    with MyResource() as r:
        r.some_function()

if __name__=='__main__':
    main()

这是程序的输出:

Constructing MyResource
Entering MyResource
Constructing MyResource
Some function
Cleaning up MyResource

我猜这是因为我在语句中做错了什么with,有效地手动调用了构造函数。我该如何纠正?

4

4 回答 4

19

您不应该从__enter__. 相反, return self( 被调用的实例__enter__。这就是为什么__init__()被调用两次 - 你调用它两次,一次在你的 with 语句中,一次在__enter__(). 这是一个正确的版本:

def __enter__(self):
    print 'Entering MyResource'
    return self
于 2011-08-19T18:24:53.500 回答
6

被调用两次的原因__init__是因为您调用了两次:

一次是当您在语句中启动一个MyResource对象时with,再一次是在with语句调用时__enter__创建并返回一个不同的实例MyResource

您的__enter__方法应该返回self

于 2011-08-19T18:27:03.823 回答
3

我的猜测是你没有return MyResource()but return self,就像self已经构建的类的实例一样。

于 2011-08-19T18:25:42.147 回答
2

将您的代码更改为:

def __enter__(self):
    print 'Entering MyResource'
    return self

__enter__方法可以让您进行初始化,而不是创建您的实例,它已经存在(自我)。

于 2011-08-19T18:27:30.080 回答