0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python初心者】with文とコンテキストマネージャーの仕組みと活用法

0
Posted at

ファイル操作などでよく使われる with 文には、実は「コンテキストマネージャー」という仕組みが裏で動いています。
今回はこの仕組みを理解し、自分でコンテキストマネージャーを作る方法についても学びました。

with文の基本的な使い方

まずは、Pythonでよく見る with 文の書き方です。

with open("example.txt", "w") as f:
    f.write("Hello, world!")

このコードでは、ファイルが自動的に開かれて閉じられます。
明示的に f.close() を書かなくても、with ブロックを抜けると自動でリソース(ここではファイル)が解放されます。

これができるのは、open() が「コンテキストマネージャー」という仕組みを提供しているからです。

コンテキストマネージャーとは?

「コンテキストマネージャー」は、リソースの開始処理と終了処理をセットで管理するための仕組みです。

Pythonでは、コンテキストマネージャーを作るには __enter__()__exit__() という特別なメソッドを使います。

自作してみる:基本的なコンテキストマネージャー

次のようにして、自分でクラスを定義することでコンテキストマネージャーを作ることができます。

class MyContext:
    def __enter__(self):
        print("開始処理:リソースを取得します")
        return "リソース"

    def __exit__(self, exc_type, exc_value, traceback):
        print("終了処理:リソースを解放します")

with MyContext() as value:
    print("withブロック内の処理:", value)
開始処理:リソースを取得します
withブロック内の処理: リソース
終了処理:リソースを解放します
  • __enter__():with文に入ったときに実行される
  • __exit__():with文から抜けたとき(例外の有無に関係なく)実行される

@contextmanager を使って簡単に書く

クラスで書くと少し面倒なときは、contextlib モジュールの @contextmanager デコレーターを使うと、関数ベースで書けて簡単です。

from contextlib import contextmanager

@contextmanager
def my_context():
    print("開始処理")
    yield "リソース"
    print("終了処理")

with my_context() as value:
    print("withブロック内の処理:", value)
開始処理
withブロック内の処理: リソース
終了処理

yield の前が __enter__() の代わり、yield の後が __exit__() の代わりになります。
シンプルなコンテキストマネージャーならこちらの方法が使いやすいです。

おわりに

with 文はただの省略記法ではなく、「リソースの開始と終了を自動管理する」という強力な仕組みを持っています。
今回はその裏側にある __enter__() / __exit__()@contextmanager を使った実装方法を学びました。

最初は少し複雑に感じましたが、ファイル以外でも応用できると知って理解が深まりました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?