Как составить список функций по шагам в Python, используя карту и уменьшить - PullRequest
0 голосов
/ 25 апреля 2018

Учитывая список функций (функций) и целое число n, я пытаюсь найти способ пошагового их составления и вернуть список каждого пошагового результата следующим образом:

compose_step([lambda x: x+3, lambda x: x+5, lambda x: x+1], 8) --> [8, 11, 16, 17]

Итак, на данный момент я выяснил, как составить список функций и вернуть результат следующим образом:

def compose(functions, n):
    def compose2(f,g):
        return lambda x: f(g(x))
    composedFunction = functools.reduce(compose2, functions, lambda x: x)
    return composedFunction(n)

Тем не менее, я очень запутался, как отслеживать каждый шаг и возвращать его в виде списка. Я предполагаю, что мне нужно как-то использовать карту, чтобы отобразить каждый пошаговый фрагмент в список. Я также придумал способ применить все функции в списке как n:

def apply_all_functions(functions, n):
    answerList = list(map(methodcaller('__call__', n), functions)))
    return answerList

Я думал о том, чтобы как-то использовать функцию composeFunction для составления нового списка пошаговых функций, вплоть до полностью составленной функции, а затем использовать это как мой новый список для apply_all_functions для достижения желаемого результата. Но в настоящее время я довольно озадачен.

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

itertools.accumulate это путь, но если вам интересно, как вы могли бы сделать это самостоятельно, вот один из способов

def apply_all (x, f = None, *fs):
  if f is None:
    return []
  else:
    next = f (x)
    return [ next ] + apply_all(next, *fs)

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(8, *funcs))
# [ 8, 11, 16, 17 ]

Если вам нужна форма в вашем оригинальном вопросе

def apply_all (fs, x):
  if not fs:
    return []
  else:
    next = fs[0](x)
    return [ next ] + apply_all(fs[1:], next)

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(funcs, 8))
# [ 8, 11, 16, 17 ]

Приведенная выше форма действует на fs[0] и fs[1:], что показывает, что это может быть выражено как ваниль reduce

from functools import reduce

def apply_all (fs, x):
  def reducer (acc, f):
    (seq, x) = acc
    next = f (x)
    return (seq + [next], next)
  return reduce(reducer, fs, ([], x)) [0]

funcs = \
  [ lambda x: x
  , lambda x: x+3
  , lambda x: x+5
  , lambda x: x+1
  ]

print(apply_all(funcs, 8))
# [ 8, 11, 16, 17 ]
0 голосов
/ 25 апреля 2018

Вы можете использовать itertools.accumulate с функцией композиции

from itertools import accumulate

def compose(f, g):
    return lambda x: f(g(x))

funcs = [lambda x: x, lambda x: x+3, lambda x: x+5, lambda x: x+1]

print([f(8) for f in accumulate(funcs, compose)])
# [8, 11, 16, 17]
...