Python用lambda函数封装作用域变量 [英] Python enclosing scope variables with lambda function

查看:72
本文介绍了Python用lambda函数封装作用域变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了这个简单的代码:

I wrote this simple code:

def makelist():
  L = []
  for i in range(5):
    L.append(lambda x: i**x)
  return L

好,现在我打电话

mylist = makelist()

因为在以后调用嵌套函数时会查找范围内的变量,所以它们都有效地记住了相同的值:因此,我希望找到循环变量在上一次循环迭代中所具有的值,但是当我检查列表时,会看到:

because the enclosing scope variable is looked up when the nested functions are later called, they all effectively remember the same value: because of this, I expected to find the value the loop variable had on the last loop iteration, but when I check my list I see:

>>> mylist[0](0)
1
>>> mylist[0](1)
4
>>> mylist[0](2)
16
>>> 

我很困惑,为什么我的代码没有保留最后一个for循环值?为什么我不必使用如下默认参数来显式保留范围值:

I'm so confused, why my code doesn't retain the last for loop values? Why I don't have to explicitly retain enclosing scope values with default arguments like this:

L.append(lambda x, i=i: i ** x)

预先感谢

推荐答案

即使 i 随时间推移获取多个值,实际上实际上只有一个变量. i 的内容在循环过程中被更改.但是闭包捕获变量,而不是值.在调用之前,lambda内部不会评估任何内容.在调用该函数时,您访问的是 i 的当前值,该值恰好是最后一个值.

Even though i takes multiple values over time, there is effectively only one variable, i. The content of i is being changed during the loop. But the closures captures variables, not values. Nothing is evaluated inside the lambda until you call it. At the time you call the function, you access the current value of i, which happens to be the last one.

关于为什么 i = i 解决问题的原因,例如

As for why i=i solves the problem, this is explained for example in The Hitchhiker's guide to Python (Common Gotchas):

Python的默认参数在定义函数时会被评估一次,而不是在每次调用函数时都会被评估(例如Ruby).这意味着,如果您使用可变的默认参数并对它进行突变,那么将来该函数的所有调用也将并且已经对该对象进行了突变.

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

因此,您创建的闭包内部发生的每个新绑定(就像外面的一样,都被命名为 i )在创建闭包时将计算其默认值.因此,您拥有适当的正确"值,可以在调用闭包时使用.

And so, each fresh binding that occurs inside the closure you create (and happen to be named i just like the one outside) has its default value being computed when creating the closure. Consequently, you have the "right" value in place, ready to be used when the closure is called.

这篇关于Python用lambda函数封装作用域变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆