【问题标题】:Python lambdas and scopingPython lambdas 和作用域
【发布时间】:2009-12-17 20:02:49
【问题描述】:

鉴于这段代码:

funcs = []
for x in range(3):
    funcs.append(lambda: x)
print [f() for f in funcs]

我希望它打印[0, 1, 2],但它却打印[2, 2, 2]。关于 lambdas 如何与范围一起工作,我是否缺少一些基本的东西?

【问题讨论】:

标签: python lambda


【解决方案1】:

这是 Python 中的一个常见问题。基本上,范围是这样的,当调用f() 时,它将使用x 的当前值,而不是形成lambda 时x 的值。有一个标准的解决方法:

funcs = []
for x in range(10):
funcs.append(lambda x=x: x)
print [f() for f in funcs]

使用lambda x = x检索并保存x的当前值。

【讨论】:

    【解决方案2】:

    x 绑定到模块级 x(从 for 循环中遗留下来)。

    更清楚一点:

    funcs = []
    
    for x in range(10):
        funcs.append(lambda: x)
    
    x = 'Foo'
    
    print [f() for f in funcs]
    
    # Prints ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo']
    

    【讨论】:

      【解决方案3】:

      你知道答案:是的。 ;) 不过,请放心,因为这对于初露头角的 pythonistas 来说是一个非常普遍的发现。当您定义一个函数或 lambda 引用未在该函数内部“创建”的变量时,它会在变量上创建一个闭包。效果是你在调用函数时得到了变量的值,而不是定义时的值。 (你期待的是后者。)

      有几种方法可以解决这个问题。首先是绑定额外的变量:

      funcs = []
      for x in range(10):
          funcs.append(lambda x=x: x)
      print [f() for f in funcs]
      # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      

      第二种方式更正式一点:

      from functools import partial
      funcs = []
      for x in range(10):
          funcs.append(partial(lambda x: x, x))
      print [f() for f in funcs]
      # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      

      【讨论】:

        猜你喜欢
        • 2012-04-26
        • 2011-06-14
        • 2013-02-09
        • 1970-01-01
        • 2016-05-31
        • 1970-01-01
        • 2015-12-24
        相关资源
        最近更新 更多