0

我正在编写一个 python 脚本,它应该接受一个函数列表,写成 lambda 表达式,并返回所有函数的组成,但是,我在脚本中有一个箭头,可能是因为我使用 lambda 表达式的方式. 似乎即使在我给返回的函数一个数字值之后,我也得到了一个函数,而不是一个数字。这是我写的:

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

我会在这个问题上有所帮助..谢谢:)

4

4 回答 4

3
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
于 2013-05-17T12:34:32.347 回答
1

你的问题是你的逻辑。

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

这将设置temp为一个函数。lst是一个函数列表,lst[i]是一个函数。你调用它,给出一个值,然后你用 lambda 创建一个新函数。然后,您返回一个提供该功能的函数。

你的返回值是一个函数,它给出一个函数,给出一个值,因此你的问题。

请注意,此代码还有其他问题。if lst == []:应该是if not lst:,例如。你也不应该按索引迭代,而是按值迭代,因为 Python 是设计的。我实际上无法弄清楚您要使用代码实现的目标,这表明通过索引进行迭代是多么难以阅读。

您的代码当前执行此操作:

  • 如果没有值,则返回一个返回第一个参数的函数。
  • 如果只有一个值,则返回列表中的函数。
  • 如果有很多值,则返回一个函数,该函数返回一个函数,该函数返回通过运行列表中的第一个函数检索到的第一个值。

我不确定你想做什么,但我很确定不是这样。

于 2013-05-17T12:30:18.093 回答
1

看起来您的循环只是重新实现了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])
于 2013-05-17T12:41:21.990 回答
0

我喜欢这种语法:

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
于 2013-05-17T14:46:56.743 回答