Как потреблять / цеплять функции "Pythonically"? - PullRequest
0 голосов
/ 08 января 2019

У меня есть набор функций f(x), g(x), s(x), t(x).

Они спроектированы так, чтобы объединяться в цепочку: f(g(s(t(x))))

Функции разработаны таким образом, что они могут быть связаны в любой последовательности. Другая часть моего кода строит последовательность в списке: [f, g, s, t]

Есть ли элегантный способ взять список и объединить вызовы функций, получив выходные данные последнего результата?

Теперь, очевидно, я могу сделать это, используя внешнюю переменную, подобную счетчику, которая отслеживает вывод, и простой for индекс приращения цикла, но мне было интересно, есть ли более Pythonic способ сделать это?

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Мартино и Амадан уже разместили «элегантное» решение. Теперь действительно питонное решение настолько глупо, просто скучно, насколько это возможно:

def chain(arg, *funcs):
    # chain(42, f, g, s) => f(g(s(42)))
    result = arg
    for func in reversed(funcs):
        result = func(result)
    return result

Это явно , а не , что большинство людей сочло бы "элегантным", но оно совершенно очевидно, читаемо, и его очень легко отследить и отладить - и это главное в философии wrt / python.

0 голосов
/ 08 января 2019

В функциональном программировании эта операция называется составлением функции. Python не имеет функции compose в стандартной библиотеке, но его довольно легко написать самостоятельно:

from functools import partial
# additional import for python 3: from itertools import reduce
def compose(*args):
    return partial(reduce, lambda x, y: y(x), reversed(args))

затем вы можете составить такие функции, как

fgst_x = compose(f, g, s, t)(x)

или

funcs = [f, g, s, t]
fgst = compose(*funcs)
fgst_x = fgst(x)
0 голосов
/ 08 января 2019

Reduce - идеальный ответ (хотя нам нужно начать с самой внутренней функции, таким образом reversed):

import functools

functions = [f, g, s, t]
y = functools.reduce(lambda a, f: f(a), reversed(functions), x)

РЕДАКТИРОВАТЬ: С постоянными параметрами, так просто, как это:

p1, p2 = 5, 42
y = functools.reduce(lambda a, f: f(a, p1, p2), reversed(functions), x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...