【问题标题】:lambda function don't closure the parameter in Python?lambda函数不关闭Python中的参数?
【发布时间】:2023-03-09 15:46:01
【问题描述】:

代码多说:


from pprint import pprint

li = []

for i in range(5):
        li.append(lambda : pprint(i))

for k in li:
        k()

产量:

4 4 4 4 4

为什么不

0 1 2 3 4

??

谢谢。

附:如果我编写完整的装饰器,它会按预期工作:



from pprint import pprint

li = []

#for i in range(5):
        #li.append(lambda : pprint(i))

def closure(i):
        def _func():
                pprint(i)
        return _func

for i in range(5):
        li.append(closure(i))

for k in li:
        k()

【问题讨论】:

标签: python lambda


【解决方案1】:

你需要做的:

lambda i=i: pprint(i)

而不是捕获i的当前值

【讨论】:

    【解决方案2】:

    它确实正确引用了i,唯一的问题是,当您的列表被填充时,i 将在迭代结束时从序列中的最后一项分配值,这就是您看到的原因4 全部结束。

    【讨论】:

      【解决方案3】:

      如果您不想使用默认参数 - 如果不小心使用参数调用可能会引入错误 - 您可以使用嵌套 lambda:

      from pprint import pprint
      
      li = []
      
      for i in range(5):
          li.append((lambda x: lambda: pprint(x))(i))
      
      for k in li:
          k()
      

      这是您的 closure 函数的匿名版本。

      【讨论】:

        【解决方案4】:

        lambda 函数在 i 变量上创建闭包。第一个for 循环完成后,i 的值是4

        然后第二个for 循环开始,所有的 lambda 函数都被执行。然后它们每个都打印i 的当前值,即4

        【讨论】:

          【解决方案5】:

          答案:因为 lambda 中的代码正在使用您的全局变量 i

          如果您删除参数i,您的第二个变体将与第一个使用 lambda 的变体相同:

          def closure():
          

          代替

          def closure(i):
          

          即函数内的代码将使用全局变量i

          【讨论】:

          • 它与变量的作用域无关,而是关闭的是对值的引用而不是对值的引用。请参阅我对这个问题的评论——如果你将for i in range 循环移动到一个函数中,所以i 在全局范围内不存在,然后在for k in li 循环之前调用该函数,它会给出相同的答案。
          • >如果将 for i in range 循环移动到一个函数中,所以 i 在全局范围内不存在,然后在 for k in li 循环之前调用该函数,它会给出相同的答案... --- 即非本地?我就是这个意思。
          • 它正在寻找变量i。由于没有函数参数i,它从外部范围获取变量i
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-09
          • 1970-01-01
          • 1970-01-01
          • 2021-03-18
          相关资源
          最近更新 更多