Python with 语句

3 投票
4 回答
1421 浏览
提问于 2025-04-16 23:58

我正在尝试使用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 个回答

3

我猜你的代码里不是在 return MyResource(),而是在 return self。因为 self 是已经创建好的这个类的实例。

6

之所以会调用两次 __init__,是因为你实际上调用了两次:

第一次是在 with 语句中创建一个 MyResource 对象的时候,第二次是在 with 语句调用 __enter__ 方法时,这个方法又创建并返回了一个不同的 MyResource 实例。

你的 __enter__ 方法应该返回 self,也就是当前的对象。

20

__enter__这个方法里,你不应该返回一个新的实例。相反,你应该返回self,也就是调用__enter__的那个实例。这就是为什么__init__()会被调用两次的原因——你在使用with语句的时候调用了一次,在__enter__()里又调用了一次。下面是一个正确的写法:

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

撰写回答