Python : 既存関数をカリー化s
[ できるかな Python ] のコーナー
最近、Pythonにハマってるので、いろいろとやってみた!
ここでは実用になるかはさておき、Pythonで出来たら楽しいって事をやってみるだけのコーナーです。
今日は、関数のカリー化です。
カリー化については、Wikipediaでも見てくださいね。
世の中の人に聞くと・・・カリー化関数の作り方ばかりが引っかかりますね。
でも、それは、別にうれしくはないはずです!
だって、それでは使いみちがないから・・・
やりたい事は既存の関数がカリー化関数になってほしいという事ではないでしょうか?
では、いってみましょう!
<材料>
- 引数を複数とる関数
- lambda式
- 特殊メソッド__call__()
<作り方のポイント>
- __call__()の利用
- 可変引数の利用
- 引数展開の利用
- lambda式の利用
- 関数呼び出し時の引数エラー(TypeError)例外の利用
カリー化from __future__ import annotations from typing import Callable import inspect class LikeCurry: def __init__(self, func: Callable[..., any], arglen: int | None = None) -> None: self.func = func self.arglen = arglen if arglen is None: argspec = inspect.getfullargspec(func) self.arglen = len(argspec.args) def curry(self, *args: any, **kwargs: any) -> Callable[..., any]: return lambda *a, **kw: self.func(*args, *a, **kw, **kwargs) def __call__(self, *args: any, **kwargs: any) -> any: arglen = len(args) print(f"{args=} {arglen=} {self.arglen=}") if arglen >= self.arglen: return self.func(*args, **kwargs) else: return LikeCurry(self.curry(*args, **kwargs), self.arglen - arglen) # def __call__(self, *args: any) -> any: # try: # return self.func(*args) # except TypeError: # return LikeCurry(self.curry(*args)) def main(): def add3(a, b, c, *, x): return a + b + c + x add3c = LikeCurry(add3) print(add3c(2,3,4,x=5)) print(add3c(2, x=5)(3,4)) print(add3c(2,3)(4)) print(add3c(2)(3)(4)) if __name__ == "__main__": main()
LikeCurry()に関数を渡すとカリー化された関数風味のオブジェクトを返してくれます。
※ただし、カリー化の意味から考えても位置引数のみだよ!デフォルト値のある関数はうまく動作しないでしょう!
コメント
コメントを投稿