LoginSignup
6
3

More than 5 years have passed since last update.

Pythonで合成関数っぽいもの

Last updated at Posted at 2018-07-30

はじめに

Pythonで合成関数っぽいものを作るときの、いわゆるPythonらしいコードの書き方です。どんな気持ちでコードを綴っているかを付記しておきます。

なにがしたいのか

たとえば

f: A \to B\\
g: B \to C

みたいな関数が2つあって、

h = g\circ f:A \to C

を作りたい。

実装例

2つ実装を載せておきます。

再帰を使う

実際に前から一つずつ適用していく方法で、一番直感的にスッキリと書けます。

def composite(*funcs):
    f, *rest = funcs
    return lambda *x: composite(*rest)(f(*x)) if rest else f(*x) 

composite(
    lambda x, y: x * y,
    lambda x: 2 * x,
    lambda x: x + 3
)(5, 7)    # (2 * (5 * 7)) + 3 = 73

関数列(*funcs)をうけとって、

  • head(f)とtail(*rest)に分解し
  • headを適用した値(f(*x))を、tailの合成関数(再帰)に適用する
  • tailに中身がなきゃheadを適用する
  • ような関数を返す

というようなイメージでコードを書いています。
再帰側から先に書いて、終わる条件をあとから付け足すようなイメージで書くと書きやすい構文になっています。

reduceを使う

関数列を畳み込む方法で、使い捨てで書きやすいです。

from functools import reduce

reduce(
    lambda f, g: lambda *x: g(f(*x)),
    [
        lambda x, y: x * y,
        lambda x: 2 * x,
        lambda x: x + 3,
    ]
)(5, 7)    # (2 * (5 * 7)) + 3 = 73

畳み込みの関数さえかければ、あとは関数列を並べるだけですね。左から畳み込みます。

  • 関数を2つうけとって
  • まるっと適用してくれる関数を返す

さいごに

Pythonはかゆいところに手が届く構文、組み込みがあってよい。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3