1

以下は架空のコードです

with dbengine.connect(**details) as db:
    cur = db.exec(sql_string)
    results = cur.fetchall()
return results

この場合、ブロック db.close() が呼び出され、db がガベージ コレクションの対象としてマークされることを期待します。

仕事で、このコードが発生するのを見始めました。

with something() as myobj:
    logger.info('I got an obj!')
return myobj

Javaのnewキーワードのように使用する必要があるかどうかはわかりません。with を使用するときにできる/できない/すべきでないことを説明する良いドキュメントを教えてもらえますか?

PSログメッセージは実際にはそれほど不自由です:-)

4

1 に答える 1

2

withステートメントが contextmanager の__enter__戻り値バインドするターゲット名( の後の名前as) は、withステートメントだけに限定されません。forループ変数と同様に、asターゲット名は現在の関数またはモジュールの名前空間にスコープされます。withこの名前は、スイートが終了しても消えたり、クリアされたりしません。

そのため、ステートメントのreturn myobj 外側withは完全に合法ですが、多少無意味です。withステートメントが保証するのは、something().__exit__()ブロックが完了したときにメソッドが呼び出されることだけです (ブロックの最後に到達するか、continue, breakorreturnステートメントのため、または例外が発生したため)。

そうは言っても、ステートメント内で return を移動するだけの方がよいでしょう:with

with something() as myobj:
    logger.info('I got an obj!')
    return myobj

with dbengine.connect(**details) as db:
    cur = db.exec(sql_string)
    return cur.fetchall()

コンテキスト マネージャーは引き続き適切にクリーンアップされますが、returnステートメントはブロックの論理的な部分のように見えwithます。実行順序は変更されません。something().__exit__()が呼び出されると、関数が戻ります。

いつものように、構文に関する Python ドキュメントwithは優れています。また、コンテキスト マネージャーに関するドキュメントと、元の提案である PEP-343を確認することもできます。

于 2013-05-27T14:05:48.863 に答える