『Effective Python』メモ

Effective Pythonを読んだのでそのメモです。

関数をトレースするデコレータ

関数呼び出しの引数と戻り値を印刷したいとする。

def trace(func):
    @wraps(func)
    def  wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        print('%s(%r, %r) -> %r' % (func.__name__, args, kwargs, result))
        return result
    return wrapper
@trace
def fibonacci(n):
    if n in (0, 1):
        return n
    return (fibonacci(n-2) + fibonacci(n-1))
fibonacci(3)

>>>
fibonacci((1, ), {}) -> 1
fibonacci((0, ), {}) -> 0
fibonacci((1, ), {}) -> 1
fibonacci((2, ), {}) -> 1
fibonacci((3, ), {}) -> 2

with句を作成するためのcontextmanagerデコレータ

with hogehoge as h を定義するには@contextmanagerを定義する。

@contextmanager
def log_level(level, name):
    logger = logging.getLogger(name)
    old_level = logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield logger # コンテキストマネージャーでyieldした値はwith文のas部分に引き渡される
    finally:
        logger.setLevel(old_level)
with log_level(loggin.DEBUG, 'my-log') as logger:
    logger.debug('this is my message')

with 文はtry/finallyブロックのロジックを再利用して見た目をスッキリさせる

様々なキュー

両端キュー(Double-ended Queue)

リストは先頭の要素の追加・削除に線形時間要するが、両端キューは定数時間でできる。
末尾の追加・削除はどちらも定数時間。

fifo = deque()
fifo.append(1)
x = fofo.popleft()
ヒープキュー(Heap Queue)

キューに入れる際に値を順番に並べてくれるため、実装者はこのデータ構造を使えば意図せず順序を保証することが可能である。

a = []
heappush(a, 5)
heappush(a, 3)
heappush(a, 7)
heappush(a, 4)

print(heappop(a), heappop(a), heappop(a), heappop(a))
>>> 
3 4 5 7