
【 Effective Python, 2nd Edition 】再帰関数の実行順序をトレースするデコレータを実装しよう - デバック用途にも重宝します! 投稿一覧へ戻る
Published 2020年6月24日21:04 by T.Tsuyoshi
今回もデコレータに関連する話題ですが、デコレータの詳細については 前回 取り上げましたので、
今回は復習も兼ねながらちょっと面白いプログラムをご紹介します。
このプログラムは、再帰関数 (recursive function) のネスト呼び出し時における実行過程を、各時点の引数と返却値と共に表示するものです。
fibonacci(4) を実行した際の表示は次のようになります。
(フィボナッチ数については wikipedia を参考にしてください )
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((1,), {}) -> 1
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((3,), {}) -> 2
fibonacci((4,), {}) -> 3
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((1,), {}) -> 1
fibonacci((0,), {}) -> 0
fibonacci((1,), {}) -> 1
fibonacci((2,), {}) -> 1
fibonacci((3,), {}) -> 2
fibonacci((4,), {}) -> 3
再帰関数、と聞くだけで結構目が回りますが、結果を確かめようと実際にコードを追うと !! イライラMAX !! という方も多いと思います。
デバッグ目的の情報としては非常に有益なものだと思いますので、イライラを募らせながら解析してみてください。
from functools import wraps
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f"{func.__name__}({args!r}, {kwargs!r}) -> {result!r}")
return result
return wrapper
@trace
def fibonacci(n):
"""n 番目のフィボナッチ数を返します"""
if n in (0, 1):
return n
return (fibonacci(n - 2) + fibonacci(n - 1))
fibonacci(4)
print(fibonacci)
print(fibonacci.__name__)
print(fibonacci.__doc__)
help(fibonacci)
import pickle
print(pickle.dumps(fibonacci))
def trace(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f"{func.__name__}({args!r}, {kwargs!r}) -> {result!r}")
return result
return wrapper
@trace
def fibonacci(n):
"""n 番目のフィボナッチ数を返します"""
if n in (0, 1):
return n
return (fibonacci(n - 2) + fibonacci(n - 1))
fibonacci(4)
print(fibonacci)
# <function fibonacci at 0x0000000001E46A60>
print(fibonacci.__name__)
# fibonacci
print(fibonacci.__doc__)
# n 番目のフィボナッチ数を返します
help(fibonacci)
# Help on function fibonacci in module __main__:
#
# fibonacci(n)
# n 番目のフィボナッチ数を返します
import pickle
print(pickle.dumps(fibonacci))
# b'\x80\x04\x95\x1a\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\tfibonacci\x94\x93\x94.'
こちらの投稿にも興味があるかもしれません...
- 【 Effective Python, 2nd Edition 】クラス作成時の setter メソッド、getter メソッドの利用は最小限に。可能な限り public 属性によるインターフェース構築を目指しましょう
- 【 Effective Python, 2nd Edition 】スレッド ( thread ) とコルーチン ( coroutine ) を混在させながら、asyncio を利用した非同期プログラムへ段階的に移行させよう!
- 【 Effective Python, 2nd Edition 】ブロッキング I/O ( blocking I/O ) とスレッド ( thread ) を利用しているプログラムを、asyncio 組み込みモジュールを利用してコルーチン ( coroutine ) と非同期 I/O ( asyncronous I/O ) を利用したプログラムにリファクタリング ( refactoring ) しよう!
- 【 Effective Python, 2nd Edition 】プログラムを並列処理 ( concurrency ) パターンへ移行するタイミングとツールを考えるシリーズ 第 6 回 - コルーチン ( coroutines ) を利用して数多くのブロッキング I/O を並列処理する fan-out、fan-in パターンを実現しよう、の巻
0 comments
コメントはまだありません。
コメントを追加する(不適切と思われるコメントは削除する場合があります)