【问题标题】:Python lambda expression compose iterator scriptPython lambda 表达式组成迭代器脚本
【发布时间】:2013-05-17 12:21:44
【问题描述】:

我正在编写一个 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

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

【问题讨论】:

  • 您的第一个 assert 在表达式周围有一些虚假的括号。如果您删除了它们,那么您可能还会注意到第二个 assert 中的括号放错了位置。

标签: python lambda-calculus


【解决方案1】:
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

【讨论】:

  • 对,这就是这里的目的。我真的无法解决这个问题,+1。
  • 坦克!绝对可以从这个脚本中学到很多东西!
【解决方案2】:

看起来你的循环只是重新实现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)

这很好地通过了你的测试。

代码高尔夫: 我无法抗拒,这是一个单行,甚至包括您对空输入列表的检查:

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

【讨论】:

    【解决方案3】:

    你的问题是你的逻辑。

    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 是设计的。我实际上无法弄清楚您要使用代码实现的目标,这表明通过索引进行迭代是多么难以阅读。

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

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

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

    【讨论】:

    • 坦克寻求帮助。欣赏它。一定会使用你的建议!
    【解决方案4】:

    我喜欢这种语法:

    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
    

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 2016-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多