contextlib — with -構文コンテキストのためのユーティリティ。
functoolsのwrapsで包んだヘルパー関数を返す
def contextmanager(func): @wraps(func) def helper(*args, **kwds): return GeneratorContextManager(func(*args, **kwds)) return helper
GeneratorContextManagerクラス(例外処理をのぞいて把握しやすくした)__enter__実行してからyieldして最後に__exit__が実行される
class GeneratorContextManager(object): """Helper for @contextmanager decorator.""" def __init__(self, gen): self.gen = gen def __enter__(self): return self.gen.next() def __exit__(self, type, value, traceback): if type is None: try: self.gen.next() except StopIteration: return else: raise RuntimeError("generator didn't stop")
実際に使う場合はこんな感じでジェネレータを包む
@contextmanager def tag(name): print "<%s>" % name yield print "</%s>" % name >>> with tag("h1"): ... print "foo" ... <h1> foo </h1>
functoolsのwraps
10.8. functools — 高階関数と呼び出し可能オブジェクトの操作
これはラッパ関数を定義するときに partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) を関数デコレータとして呼び出す便宜関数です。