これが呼び出し可能なチェーンと同じくらい関数チェーンであるかどうかはわかりませんが、関数は呼び出し可能であるため、害はないと思います。いずれにせよ、私がこれを行うことを考えることができる2つの方法があります:
サブクラス化intと定義__call__:
最初の方法は、更新された値でそれ自体の新しいインスタンスを返すものintを定義するカスタムサブクラスを使用する__call__ことです。
class CustomInt(int):
def __call__(self, v):
return CustomInt(self + v)
関数addは、CustomIntインスタンスを返すように定義できるようになりました。インスタンスは、それ自体の更新された値を返す呼び出し可能オブジェクトとして、連続して呼び出すことができます。
>>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44)
50
さらに、intサブクラスとして、戻り値はsの__repr__および__str__動作を保持しますint。ただし、より複雑な操作の場合は、他のダンダーを適切に定義する必要があります。
@Caridorcがコメントで述べたように、add単純に次のように書くこともできます。
add = CustomInt
クラスの名前をaddではなくに変更してCustomIntも、同様に機能します。
クロージャを定義し、値を生成するために追加の呼び出しが必要です。
私が考えることができる他の唯一の方法は、結果を返すために余分な空の引数呼び出しを必要とする入れ子関数を含みます。私は使用しておらずnonlocal、Python間で移植できるようにするために、関数オブジェクトに属性をアタッチすることを選択しています。
def add(v):
def _inner_adder(val=None):
"""
if val is None we return _inner_adder.v
else we increment and return ourselves
"""
if val is None:
return _inner_adder.v
_inner_adder.v += val
return _inner_adder
_inner_adder.v = v
return _inner_adder
これは継続的にそれ自体(_inner_adder)を返し、avalが指定されている場合はインクリメント(_inner_adder += val)し、指定されていない場合は値をそのまま返します。私が述べたように()、インクリメントされた値を返すために追加の呼び出しが必要です。
>>> add(1)(2)()
3
>>> add(1)(2)(3)()
6