Tips

Python 関数のカリー化

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()

実行結果

新連載はじまりました!独学で学ぶPython基礎 連載リンク

独学で学ぶ-Pythonプログラミング 連載

Recent News

Recent Tips

Tag Search