如果我做的功能两个列表lambda表达式:生成函数与蟒蛇
def makeFun(i):
return lambda: i
a = [makeFun(i) for i in range(10)]
b = [lambda: i for i in range(10)]
为什么名单a
和b
不相等?
例如:
>>> a[2]()
2
>>> b[2]()
9
如果我做的功能两个列表lambda表达式:生成函数与蟒蛇
def makeFun(i):
return lambda: i
a = [makeFun(i) for i in range(10)]
b = [lambda: i for i in range(10)]
为什么名单a
和b
不相等?
例如:
>>> a[2]()
2
>>> b[2]()
9
技术上,lambda表达式是关闭在i
,在全球范围内,这是最后一组到9的可见这是相同i
被所有10个lambda表达。例如,
i = 13
print b[3]()
在makeFun
功能,拉姆达上i
关闭被调用该函数时的已定义。那十个不同i
s。
lambda表达式在Python份额他们所创建的变量的作用域在你的第一种情况,拉姆达的范围makeFun的。在第二种情况下,它是全球性的i
,它是9,因为它是循环中的剩余物。
这就是我理解的也无妨......
好的。列表理解中的lambda每次都会看到相同的本地i
。
你可以把它改写为:
a = []
for i in range(10):
a.append(makefun(i))
b = []
for i in range(10):
b.append(lambda: i)
具有相同的结果。
我不确定你想说什么。在你的例子中,'b [2]()'也返回9. – 2009-12-03 17:06:52
我说它相当于列表解析。不是说a和b是一样的。 我觉得拼写出来的'for'循环会让我们更容易看到'i'从哪里来。 – 2009-12-03 17:31:54
一组函数(a)中传递的参数和其他的(b)中运行在一个全局变量,然后将其设置为9.检查拆卸操作:
>>> import dis
>>> dis.dis(a[2])
1 0 LOAD_DEREF 0 (i)
3 RETURN_VALUE
>>> dis.dis(b[2])
1 0 LOAD_GLOBAL 0 (i)
3 RETURN_VALUE
>>>
正如其他人指出,范围是问题。请注意,您可以通过添加额外的参数lambda表达式,并分配给它的默认值解决这个问题:
>> def makeFun(i): return lambda: i
...
>>> a = [makeFun(i) for i in range(10)]
>>> b = [lambda: i for i in range(10)]
>>> c = [lambda i=i: i for i in range(10)] # <-- Observe the use of i=i
>>> a[2](), b[2](), c[2]()
(2, 9, 2)
结果是i
现在明确地放在局限于lambda
表达范围。
要添加一些清晰度(至少在我的脑海里)
def makeFun(i): return lambda: i
a = [makeFun(i) for i in range(10)]
b = [lambda: i for i in range(10)]
一个使用makeFun(我),这是自变量的函数。
b使用lambda:i,这是一个函数而不是参数。它使用的我是从以前的
非常不同,以使a和b等于我们可以做出两种功能使用不带参数:
def makeFun(): return lambda: i
a = [makeFun() for i in range(10)]
b = [lambda: i for i in range(10)]
现在,这两个功能使用全局我
>>> a[2]()
9
>>> b[2]()
9
>>> i=13
>>> a[2]()
13
>>> b[2]()
13
或(更有用)使两个使用一个参数:
def makeFun(x): return lambda: x
a = [makeFun(i) for i in range(10)]
b = [lambda x=i: x for i in range(10)]
我故意改变我与x其中变量是本地的。 现在:
>>> a[2]()
2
>>> b[2]()
2
成功!
好吧,现在这对我来说很合理。谢谢! – Anssi 2009-12-03 17:15:16