【问题标题】:What's going on with the lambda expression in this python function?这个 python 函数中的 lambda 表达式是怎么回事?
【发布时间】:2010-10-24 21:38:58
【问题描述】:

为什么这种创建柯里化函数列表的尝试不起作用?

def p(x, num):
    print x, num

def test():
    a = []
    for i in range(10):
        a.append(lambda x: p (i, x))
    return a

>>> myList = test()
>>> test[0]('test')
9 test
>>> test[5]('test')
9 test
>>> test[9]('test')
9 test

这是怎么回事?

实际上我期望上面的函数做的一个函数是:

import functools
def test2():
    a = []
    for i in range (10):
        a.append(functools.partial(p, i))
    return a


>>> a[0]('test')
0 test
>>> a[5]('test')
5 test
>>> a[9]('test')
9 test

【问题讨论】:

  • 既然你有一个使用 functools.partial 的解决方案,那么问题是什么?
  • 问题是,为什么第一种方法不起作用?

标签: python lambda


【解决方案1】:

在 Python 中,在循环和分支中创建的变量没有作用域。您使用lambda 创建的所有函数都引用了相同的i 变量,该变量在循环的最后一次迭代中设置为9

解决方案是创建一个返回函数的函数,从而确定迭代器变量的范围。这就是functools.partial() 方法有效的原因。例如:

def test():
    def makefunc(i):
        return lambda x: p(i, x)
    a = []
    for i in range(10):
        a.append(makefunc(i))
    return a

【讨论】:

    【解决方案2】:

    你也可以将 i 绑定到惰性的外部 lambda。

    def p(x, num):
        print x, num
    
    def test():
        a = []
        for i in range(10):
            a.append((lambda i :lambda x: p (i, x))(i))
        return a
    

    【讨论】:

      【解决方案3】:

      我总是对为什么这不起作用感到困惑。感谢您的解释,'a paid nerd'。我个人更喜欢这个解决方案:

      for i in range(10):
          a.append(lambda num, val_i=i: p (val_i, num))
      

      注意lambdaval_i=i 默认参数,它可以在循环期间捕获i 的瞬时值,同时仍然有效地使lambda 成为1 个变量的函数。 (顺便说一句:将您的 x 更改为 num 以匹配 p 的定义。)我更喜欢它,因为:

      1. 它非常接近最初的想法,并且避免了必须定义一个新的命名函数,这正是 lambda 的目的......
      2. 避免导入functools
      3. 并避免重叠 lambda...

      刚刚搜索了一下,发现有同样问题的更详细解释:Scope of python lambda functions and their parameters

      【讨论】:

      【解决方案4】:

      我问了一个类似的问题,得到了两个答案。一个与这里接受的答案基本相同,另一个不太清楚但稍微简洁一些。

      Dynamically creating a menu in Tkinter. (lambda expressions?)

      【讨论】:

      • 其中包括(我现在终于明白了)lambda x=x : ... hack。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-18
      • 2011-08-25
      • 2022-12-09
      • 1970-01-01
      • 2023-04-09
      • 2011-12-17
      • 2011-09-26
      相关资源
      最近更新 更多