изменение рекурсивной функции на итерацию - PullRequest
0 голосов
/ 26 сентября 2018

Я хотел создать цепочку <ufunc>, и это то, что я реализовал, используя функцию functors.reduce.Например:

from functools import reduce
fns1 = [np.cos, np.sin, np.tan]
x = reduce(  lambda f, f1: lambda m: f1(f(m)) , fns1, lambda m: m )
x(0.5)

Хотя это очень просто, я хотел сделать код более читабельным.Поэтому я сгенерировал итеративную версию:

def fnLong(fnList):

    curFn = lambda m: m
    for f in fnList:
        currF = lambda m: f(currF(m))

    return currF

Эта функция фактически создает бесконечный цикл.Я считаю, что обе функции должны быть абсолютно одинаковыми, но, видимо, нет.Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 26 сентября 2018

Проблема возникает из выражения lambda, поскольку она решается во время вызова.Эта функция приводит к различным проблемам, когда вы создаете группу lambda s внутри for loop.В своем коде вы используете lambda внутри lambda внутри for loop, а затем возвращаете получившийся вложенный lambda, чтобы вызвать его позже.

Вы можете решить проблему следующим образом:

def fnLong(fnList):

    currF = lambda m: m
    for f in fnList:
        currF = lambda m, f=f, currF=currF: f(currF(m))

    return currF

currF=currF и f=f добавлены для указания аргументов (связывания аргументов) для каждого lambda выражений внутри for loop во время создания этого самого lambda.Это решение работает, потому что значения аргументов по умолчанию создаются при создании (определении) функции, а не при вызове функции.currF=currF позволяет избежать рекурсии, f=f позволяет избежать использования только последней функции в fnList.

На мой взгляд, трудно сказать, является ли эта версия более читабельной, чем оригинальная.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...