Não sei se isso é encadeamento de funções tanto quanto é encadeamento chamável , mas, como as funções são chamáveis, acho que não houve nenhum problema. De qualquer forma, posso pensar em fazer isso de duas maneiras:
Subclassificando int
e definindo __call__
:
A primeira forma seria com uma int
subclasse personalizada que define o __call__
que retorna uma nova instância de si mesma com o valor atualizado:
class CustomInt(int):
def __call__(self, v):
return CustomInt(self + v)
A função add
agora pode ser definida para retornar uma CustomInt
instância, que, como um chamável que retorna um valor atualizado de si mesma, pode ser chamada em sucessão:
>>> def add(v):
... return CustomInt(v)
>>> add(1)
1
>>> add(1)(2)
3
>>> add(1)(2)(3)(44)
50
Além disso, como uma int
subclasse, o valor devolvido retém a __repr__
e __str__
comportamento de int
s. Para operações mais complexas, porém, você deve definir outros dunders apropriadamente .
Como @Caridorc observou em um comentário, add
também poderia ser escrito simplesmente como:
add = CustomInt
Renomear a classe para em add
vez de CustomInt
também funciona de maneira semelhante.
Defina um fechamento, requer uma chamada extra para gerar o valor:
A única outra maneira que consigo pensar envolve uma função aninhada que requer uma chamada de argumento vazio extra para retornar o resultado. Estou não usando nonlocal
e opt para anexar atributos para os objetos de função para torná-lo portátil entre Pythons:
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
Este retorna continuamente a si mesmo ( _inner_adder
) que, se a val
for fornecido, o incrementa ( _inner_adder += val
) e, se não, retorna o valor como está. Como mencionei, ele requer uma ()
chamada extra para retornar o valor incrementado:
>>> add(1)(2)()
3
>>> add(1)(2)(3)()
6