Python 関数のカリー化(起動の遅延)
概要
本記事ではPythonを使ってカリー化を紹介する。
カリー化は、引数の付与や、関数の起動を、
一度に行わず、分割して行うための手法である。
通常の関数との対比
カリー化された関数 | 通常の関数 | |
---|---|---|
引数の付与 | 複数回に分割できる | 実行時にすべての引数を渡す |
関数の実行 | 引数をすべて渡した後も実行を引き延ばせる | 引数が渡された瞬間実行される |
フォーマット
def 元の関数(すべての引数):
操作
def カリー化関数(最初に与える引数):
def process(二回目に与える残りの引数):
return 元の関数(すべての引数)
return process
実質的か形式的か
実質的なカリー化
引数が一度に用意できないときにつかう
狭義のカリー化
最初の引数のみを最初に取り、2番目以降の引数は後からとる。
一般的に、カリー化と呼ばれるのはこれだけである。
# カリー化
## 元関数
def mapping(original_list, conversion_rule):
return [conversion_rule(item) for item in original_list]
## 狭義のカリー化
def mapping_curried_in_narrow_sense(original_list):
def process(conversion_rule):
return mapping(original_list, conversion_rule)
return process
## カリー化された関数の実行
if __name__ == "__main__":
mapped_list_1 = mapping(["A", "B", "C"], lambda e : e * 3)
mapped_list_2 = mapping_curried_in_narrow_sense(["A", "B", "C"])(lambda e : e * 3)
print(mapped_list_1)
print(mapped_list_2)
実行結果
広義のカリー化
任意の引数を最初に取り、残りの引数は後からとる
# カリー化
## 元関数
def mapping(original_list, conversion_rule):
return [conversion_rule(item) for item in original_list]
## 広義のカリー化
def mapping_curried_in_broader_sense(conversion_rule):
def rest_of_function(original_list):
return mapping(original_list, conversion_rule)
return rest_of_function
## カリー化された関数の実行
if __name__ == "__main__":
mapped_list_1 = mapping(["A", "B", "C"], lambda e : e * 3)
mapped_list_2 = mapping_curried_in_broader_sense(lambda e : e * 3)(["A", "B", "C"])
print(mapped_list_1)
print(mapped_list_2)
実行結果
形式的なカリー化
最初に必要な引数をすべて与え、最後の起動のみが残ったゼロ引数関数を与える
純粋に起動を遅らせるためだけのカリー化である。
# カリー化
## 元関数
def mapping(original_list, conversion_rule):
return [conversion_rule(item) for item in original_list]
## 形式的カリー化
def mapping_curried_for_delayed_execution(original_list, conversion_rule):
def process():
return mapping(original_list, conversion_rule)
return process
## カリー化された関数の実行
if __name__ == "__main__":
mapped_list_1 = mapping(["A", "B", "C"], lambda e : e * 3)
mapped_list_2 = mapping_curried_for_delayed_execution(["A", "B", "C"], lambda e : e * 3)()
print(mapped_list_1)
print(mapped_list_2)
実行結果
元の関数のないカリー化
元の関数が存在しないカリー化も存在する。
ただし、定義されていないだけで、
どのように定義すればいいかは常に想定できる。
# 元関数のないカリー化
## 実際にはないが仮定されうる元関数
"""
def execute(action, *args, **kwargs):
return action(*args, **kwargs)
"""
## カリー化
def execution(action, *args, **kwargs):
def process():
return action(*args, **kwargs)
return process
if __name__ == "__main__":
print_execution = execution(print, "A", "B", "C")
print_execution()