문제

I'm writing a python script that should take a list of functions, written as lambda expressions, and return the compose of all the function, but, I have an arrow in the script, maybe because of the way I'm using lambda expression. It seems like even after I give the returned function a number value, I get back a function, and not a number. This is what I've wrote:

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

this is a tast for the function I've wrote, which says I have a mistake.

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

I would apreciate some halp on this problem.. thanks :)

도움이 되었습니까?

해결책 2

It looks like your loop is just reimplementing what reduce does. Here's a functional look at your function composition problem:

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)

This passes your tests just fine.

CODE GOLF: I couldn't resist, here is a one-liner, even including your check for an empty input list:

compose1 = lambda fnlist: reduce(lambda fn1,fn2: lambda x : fn1(fn2(x)), 
                                  fnlist or [lambda x:x])

다른 팁

def compose(*funcs):
    """
    compose(func[,...[, func]]) -> function

    Return the composition of functions.
    For example, compose(foo, bar)(5) == foo(bar(5))
    """
    if not all(callable(func) for func in funcs):
        raise TypeError('argument must be callable')
    funcs = funcs[::-1]

    def composition(*args, **kwargs):
        args = funcs[0](*args, **kwargs)
        for func in funcs[1:]:
            args = func(args)
        return args
    return composition

f = compose(*[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 = compose(*[lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
    assert f(x) == ((x + 1) * 2) - 1

Your issue here is your logic.

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

This will set temp to a function. lst is a list of functions, lst[i] is a function. You call that, to give a value, and then you make a new function with lambda. You then return a function that gives that function.

Your return value is a function, that gives a function, that gives a value, hence your issue.

As a note, this code has other problems. if lst == []: should be if not lst:, for example. You should also never iterate by index, and instead iterate by value, as Python is designed. I can't actually work out what you are trying to achieve with your code, which shows how hard to read iterating by index is.

Your code currently does this:

  • If there are no values, return a function that returns the first argument.
  • If there is one value, return the function in the list.
  • If there are many values, return a function that returns a function that returns the first value retrieved by running the first function from the list.

I'm not sure what you were trying to do, but I'm pretty sure that isn't it.

I like this syntax:

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

The implementation is surprisingly trivial:

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top