0
2

More than 3 years have passed since last update.

with文のカスタマイズ(Python)

Posted at

概要

with文を自分でも活用できるようにする。

内容

環境

macOS Catalina
Python 3.7.0

解決策1 準備

classを定義する。

with1.py
class Obj():
    def __init__(self, name):
        print('------start')
        self.name = name
    def __enter__(self):
        return f'hello, {self.name}'
    def __exit__(self, type, value, traceback):
        #Exception handling here
        print(f'with or without exception, finished. bye, {self.name}')
        print('------end\n')

__init__, __enter__, __exit__を使い、__enter__asで使うものを返す。

解決策1 実行

with1.py
with Obj('yaruo') as message:
    print(message)
with Obj('yaruo') as message:
    print(message)
    raise RuntimeError()
output
------start
hello, yaruo
with or without exception, finished. bye, yaruo
------end

------start
hello, yaruo
with or without exception, finished. bye, yaruo
------end

Traceback (most recent call last):
  File "with1.py", line 25, in <module>
    raise RuntimeError()
RuntimeError

できた。

解決策2 準備

builtinのcontextlibを使う。

with2.py
import contextlib

@contextlib.contextmanager
def context(name):
    print('------start')
    try:  #Exception handling can be written in except:
        yield f'hello, {name}'
    finally:
        print(f'with or without exception, finished. bye, {name}')
        print('------end\n')

yieldasで使うものを返す。

解決策2 実行

with2.py
with context('yaruo') as message:
    print(message)
with context('yaruo') as message:
    print(message)
    raise RuntimeError()
output
------start
hello, yaruo
with or without exception, finished. bye, yaruo
------end

------start
hello, yaruo
with or without exception, finished. bye, yaruo
------end

Traceback (most recent call last):
  File "with2.py", line 25, in <module>
    raise RuntimeError()
RuntimeError

蛇足

  • return:終了のイメージ
  • yield:一時停止のイメージ

終了処理のほか、一時的に変数を変更したい時にも使える。

import contextlib
class Config:
    a = False

@contextlib.contextmanager
def a_True():
    backup, Config.a = Config.a, True
    try:
        yield
    finally:
        Config.a = backup

with a_True():
    print(Config.a)  # True
print(Config.a)  # False

参考にさせていただいた頁・本

感想

with文を活用する方法がわかって良かった。

今後

Pythonicなコード目指して活用していきたい。

0
2
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
2