例外がスローされた場合にオブジェクトを確実にファイナライズする手段としてpythonのwith
ステートメントを使用することに慣れています。これは通常次のようになります
with file.open('myfile.txt') as f:
do stuff...
これは略記です
f = file.open('myfile.txt'):
try:
do stuff...
finally:
f.close()
または、クラスが提示する可能性のあるその他のファイナライズルーチン。
私は最近、これを提示するOpenGLを処理するコードに遭遇しました。
with self.shader:
(Many OpenGL commands)
as
キーワードがないことに注意してください。これは__enter__
および__exit__
クラスのメソッドはまだ呼び出されますが、オブジェクトがブロック内で明示的に使用されることはありません(つまり、オブジェクトはグローバルまたは暗黙的な参照を通じて機能します)?それとも私を避けている他の意味がありますか?
コンテキストマネージャはオプションを使用してオブジェクトを返し、as
で指定された識別子に割り当てることができます。そして、as
によって割り当てられるのは___enter__
_メソッドによって返されるオブジェクトであり、必ずしもコンテキストマネージャ自体ではありません。
_as <identifier>
_を使用すると、open()
呼び出しのようにnewオブジェクトを作成するときに役立ちますが、すべてのコンテキストマネージャーがコンテキストだけで作成されるわけではありません。たとえば、再利用可能で、すでに作成されている場合があります。
データベース接続を取ります。データベース接続は1回だけ作成しますが、多くのデータベースアダプターでは、接続をコンテキストマネージャーとして使用できます。コンテキストを入力してトランザクションを開始し、トランザクションを終了してトランザクションをコミット(成功時)またはロールバック(例外がある場合)します。
_with db_connection:
# do something to the database
_
ここで新しいオブジェクトを作成する必要はありません。コンテキストはdb_connection.__enter__()
で入力し、db_connection.__exit__()
で再び終了しますが、すでにhavea接続オブジェクトへの参照。
これでできます入力すると、接続オブジェクトがカーソルオブジェクトを生成します。ここで、そのカーソルオブジェクトをローカル名で割り当てることには意味があります。
_with db_connection as cursor:
# use cursor to make changes to the database
_
_db_connection
_はまだここでは呼び出されず、以前から存在しており、すでに参照されています。しかし、生成されたdb_connection.__enter__()
はすべてcursor
に割り当てられ、そこからそのまま使用できます。
これは、ファイルオブジェクトで発生することです。 open()
はファイルオブジェクトを返し、fileobject.__enter__()
はファイルオブジェクトitselfを返すため、open()
を使用できますwith
ステートメントを呼び出しおよび新しく作成されたオブジェクトへの参照を2つではなく1つのステップで割り当てます。その小さなトリックがなければ、以下を使用する必要があります。
_f = open('myfile.txt')
with f:
# use `f` in the block
_
これらすべてをシェーダーの例に適用します。 _self.shader
_への参照はすでにあります。 self.shader.__enter__()
が_self.shader
_への参照を再び返す可能性は非常に高いですが、完全にサービス可能な参照が既にあるので、なぜそのための新しいローカルを作成するのですか?