Лямбда-выражение Python составляет скрипт итератора

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

def compose1(lst):
    if lst == []:
        return lambda x: x
    else:
        temp = (lst[len(lst)-1])
        for i in range(len(lst)-2,-1,-1):
            temp = lambda x: lst[i](temp)
        return lambda x: temp

это пример функции, которую я написал, которая говорит, что у меня есть ошибка.

f = compose1([lambda x: x+1, lambda x: x*2, lambda x: x-1])
for x in range(10):
    assert (f(x) == 1 + (x - 1) * 2)
f = compose1([lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
    assert (f(x) == (x + 1) * 2) - 1

Я был бы признателен за помощь в решении этой проблемы .. спасибо :)


person Gal Hyams    schedule 17.05.2013    source источник
comment
В вашем первом assert есть несколько ложных скобок вокруг выражения. Если вы их удалили, вы также можете заметить, что скобки во втором assert находятся не на том месте.   -  person Duncan    schedule 17.05.2013


Ответы (4)


Похоже, ваш цикл просто переопределяет то, что делает reduce. Вот функциональный взгляд на вашу проблему с композицией функций:

def compose1(fnlist):
    if not fnlist:
        return lambda x: x

    # compose 1 function of x from two others
    def compose2fns(fn1, fn2):
        return lambda x : fn1(fn2(x))
    # or if you really love lambdas
    # compose2fns = lambda fn1,fn2: lambda x: fn1(fn2(x))

    # use reduce to cumulatively apply compose2fns to the functions
    # in the given list
    return reduce(compose2fns, fnlist)

Это проходит ваши тесты просто отлично.

CODE GOLF: я не мог устоять, вот однострочное, даже включая вашу проверку на пустой список ввода:

compose1 = lambda fnlist: reduce(lambda fn1,fn2: lambda x : fn1(fn2(x)), 
                                  fnlist or [lambda x:x])
person PaulMcG    schedule 17.05.2013

Ваша проблема здесь в вашей логике.

for i in range(len(lst)-2,-1,-1):
    temp = lambda x: lst[i](temp)
return lambda x: temp

Это установит temp в функцию. lst — список функций, lst[i] — функция. Вы вызываете это, чтобы дать значение, а затем создаете новую функцию с лямбдой. Затем вы возвращаете функцию, которая дает эту функцию.

Ваше возвращаемое значение - это функция, которая дает функцию, которая дает значение, отсюда и ваша проблема.

Как примечание, у этого кода есть и другие проблемы. Например, if lst == []: должно быть if not lst:. Вы также никогда не должны выполнять итерацию по индексу, а вместо этого выполнять итерацию по значению, как разработан Python. На самом деле я не могу понять, чего вы пытаетесь достичь с помощью своего кода, который показывает, насколько сложно читать итерацию по индексу.

Ваш код в настоящее время делает это:

  • Если значений нет, вернуть функцию, которая возвращает первый аргумент.
  • Если есть одно значение, вернуть функцию в списке.
  • Если значений много, верните функцию, которая возвращает функцию, возвращающую первое значение, полученное при запуске первой функции из списка.

Я не уверен, что вы пытались сделать, но я почти уверен, что это не так.

person Gareth Latty    schedule 17.05.2013
comment
Танки в помощь. Ценить это. Обязательно воспользуюсь вашими услугами! - person Gal Hyams; 17.05.2013

Мне нравится этот синтаксис:

f = do (lambda x: x-1) (lambda x: x*2) (lambda x: x+1)

for x in range(10):
    assert f(x) == 1 + (x - 1) * 2

Реализация на удивление тривиальна:

class do(object):
    def __init__(self, x):
        self.fns = [x]
    def __call__(self, x):
        if callable(x):
            self.fns.append(x)
            return self
        for f in self.fns:
            x = f(x)
        return x
person georg    schedule 17.05.2013

person    schedule
comment
Правильно, вот в чем цель. Я действительно не мог решить это, +1. - person Gareth Latty; 17.05.2013
comment
Танки! Определенно есть чему поучиться у этого сценария! - person Gal Hyams; 17.05.2013