高階関数、デコレータ
高階関数...関数を関数に渡したり、戻り値として関数を返したり。
関数に機能を追加できたりする。
print(int(3.14)) # 3 print(int("100", 3)) # 9 :3進法の100は10進法の9 def arg_check(func, arg): print(arg) return func(arg) print(arg_check(int, 3.14)) # 3.14 # 3 def args_check(func): def check(*args): print("args:", args) return func(*args) return check def adder(a, b): return a + b f = args_check(adder) print(f(3, 4)) # args: (3, 4) # 7 print(args_check(int)("100", 3)) # args: ('100', 3) # 9
関数内の関数は変数と同様に扱える。
@マークをつけたデコレータを使って同様の動作ができる
def args_check(func): def check(*args): print("args:", args) return func(*args) return check @args_check def multiple(a, b): return a * b print(multiple(2, 10)) # args: (2, 10) # 20
lru_cacheデコレータ
(Least-recently-used cache decorator)
関数の引数と戻り値を記憶し、同じ引数で呼ばれたら関数を実行せずに値を返す。
同じ引数で何度も呼び出す関数だと劇的に速くなる。
counter = 0 def fib1(n): global counter counter += 1 if n in [0, 1]: return 1 return fib1(n - 1) + fib1(n - 2) print(fib1(24)) print(counter, "回の関数呼び出し") # 75025 # 150049 回の関数呼び出し from functools import lru_cache counter = 0 @lru_cache(maxsize=1024) def fib2(n): global counter counter += 1 if n in [0, 1]: return 1 return fib2(n - 1) + fib2(n - 2) print(fib2(24)) print(counter, "回の関数呼び出し") # 75025 # 25 回の関数呼び出し
lru_cacheなしだと関数を15万回呼び出していたが、lru_cacheありだと25回で済む。
参考:
10.2. functools — 高階関数と呼び出し可能オブジェクトの操作 — Python 3.6.1 ドキュメント