3

Pythonのステートメントを試してwithいますが、次のコードリストでは、__init__メソッドが2回呼び出され、__exit__メソッドが1回呼び出されることがわかりました。これはおそらく、このコードが何か有用なことをした場合、リソースリークが発生することを意味します。

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__()、2回呼び出されます。withステートメントで1回、withステートメントで1回、2回呼び出します__enter__()。正しいバージョンは次のとおりです。

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

2回呼び出される理由__init__は、2回呼び出すためです。

MyResourceステートメントでオブジェクトを開始したときと、ステートメントが呼び出されwithたときにもう一度、次の別のインスタンスを作成して返します。with__enter__MyResource

代わりに、__enter__メソッドが返さselfれます。

于 2011-08-19T18:27:03.823 に答える
3

私の推測では、すでに構築されたクラスのインスタンスのようにreturn MyResource()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 に答える