当我直接 return 一个匿名函数的时候返回 0,2,4,6
def testFun():
return(lambda x : i*x for i in range(4))
for everyLambda in testFun():
print(everyLambda(2))
& python test.py
0
2
4
6
但是当我把匿名函数作为一个 temp 来返回的时候,结果却是 6,6,6,6
def testFun():
temp = [lambda x : i*x for i in range(4)]
return temp
for everyLambda in testFun():
print(everyLambda(2))
& python test.py
6
6
6
6
求大神解释解释,这是为什么呀,急求明天就要面试了好紧张
1
XiaoxiaoPu 2018-08-23 21:13:55 +08:00
两段代码的区别不是“把匿名函数作为一个 temp 来返回”,而是第一段代码返回的是生成器,在 for 循环的时候 i 才实际增加,第二段代码返回的是数组,在 for 循环开始的时候 i 已经增加到 3 了
|
2
newmind 2018-08-23 21:27:42 +08:00
第一个是括号(), 为生成器, 返回 generator
第二个是中括号[], 为列表生成式, 返回数组 |
3
HelloAmadeus 2018-08-23 21:34:24 +08:00
```
tmp = [lambda x: x*i for i for range(4)] ``` 返回的是: ``` tmp = [lambda x: x*3, ...] ``` ``` tmp = (lambda x: x*i for i for range(4)) 返回的是: ``` tmp = (lambda x: x*0, lambda x: x**1, ...) # 这是一个生成器 ``` 列表表达式是即时计算的, 而生成器是迭代时才会计算. 返回的 lamda 匿名函数在查找 i 变量的时候, 列表表达式已经算计完了, 此时的 i 值为 3, 所以计算的返回结果是 6, 而在生成器计算的时候, `for i in range(4)` 的计算是惰性的, 只有你去迭代生成器的时候, i 的值才会 +1. 所以 lambda 表达式查找的 i 变量是 0, 1, 2, 3 的序列. |
4
lixm 2018-08-23 22:23:46 +08:00 1
```python
from dis import dis f1 = next((lambda x : i*x for i in range(4))) dis(f1) f2 = [lambda x : i*x for i in range(4)][0] dis(f2) ``` 都取第 0 个函数出来, 反编译一下就知道, 这两个唯一的区别就是 i, f1 是 LOAD_DEREF i 作为闭包传入 f2 是 LOAD_GLOBAL i 作为全局变量传入 ```python print(f1.func_closure[0].cell_contents) ``` 可以看出 作为闭包传入的 i 的值为 0 ```python print(f2.func_globals['i']) ``` 可以看出 作为全局变量传入的 i 的值为 3 为什么会这样呢?因为 Python 里,一切都是引用, 在第一个例子里, 因为生成器是惰性求值, 你可以理解在执行 next, 或者 for 循环的时候, 才求出 i 的值, 所以 i 的值从 0 递增到 3。 在第二个例子里, 列表并不是惰性求值,i 作为一个引用, 值已经变为 3 了 可能说的不是很清楚, 抱歉 |
5
lolizeppelin 2018-08-23 22:27:23 +08:00 via iPad
这不是 python 的问题。 我所知的语言里只有 erlang 不出这个问题
js 之类的一鸟样 |
6
cyrbuzz 2018-08-24 08:54:02 +08:00
我比较好奇有什么情况下会用这样的写法。
|
7
ipwx 2018-08-24 10:03:43 +08:00
|
8
whoami9894 2018-08-24 23:12:17 +08:00 via Android
补充一下,python 中只有 def,class,lambda 会产生作用域,所以这里 for 循环结束后 i 依然存在为 4,这里方括号列表解析生成的 lambda 可以看作是宏,所以会得到 6666 的结果
|
9
josephshen 2018-08-26 17:55:53 +08:00 via iPhone
我告诉你上面的解释是出现了显现给的解释,原因根源是 python 这门语言的设计问题,导致了分不清申明和赋值
|
10
josephshen 2018-08-26 17:57:09 +08:00 via iPhone
显示->现象
|
11
Alerta OP @HelloAmadeus 感谢感谢 一下子明白了
|