A biblioteca padrão do Python é vasta e minha intuição diz que deve haver uma maneira de fazer isso, mas simplesmente não consigo descobrir. Isto é puramente para fins de curiosidade e aprendizagem:
Eu tenho duas funções simples:
def increment(x):
return x + 1
def double(x):
return x * 2
e quero compô-los em uma nova função double_and_increment
. É claro que eu poderia simplesmente fazer isso da seguinte forma:
double_and_increment = lambda x: increment(double(x))
mas eu também poderia fazer isso de uma forma mais complicada, mas talvez mais "ergonomicamente escalonável":
import functools
double_and_increment = functools.partial(functools.reduce, lambda acc, f: f(acc), [double, increment])
Ambas as opções acima funcionam bem:
>>> double_and_increment(1)
3
Agora, a questão é: existem ferramentas na biblioteca padrão que permitiriam alcançar a composição sem quaisquer lambdas, funções regulares ou classes definidas pelo usuário.
A primeira intuição é substituir a lambda acc, f: f(acc)
definição na functools.reduce
chamada por operator.call
, mas isso infelizmente leva os argumentos na ordem inversa:
>>> (lambda acc, f: f(acc))(1, str) # What we want to replace.
>>> '1'
>>> import operator
>>> operator.call(str, 1) # Incorrect argument order.
>>> '1'
Tenho um palpite de que usar functools.reduce
ainda é a maneira de realizar a composição, mas, de forma alguma, não consigo descobrir uma maneira de me livrar do lambda definido pelo usuário.
Alguns métodos prontos para uso que me aproximaram:
import functools, operator
# Curried form, can't figure out how to uncurry.
functools.partial(operator.methodcaller, '__call__')(1)(str)
# The arguments needs to be in the middle of the expression, which does not work.
operator.call(*reversed(operator.attrgetter('args')(functools.partial(functools.partial, operator.call)(1, str))))
Examinei todas as questões existentes, mas elas são completamente diferentes e dependem do uso de funções definidas pelo usuário e/ou lambdas.