
当我直接 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 Aug 23, 2018 两段代码的区别不是“把匿名函数作为一个 temp 来返回”,而是第一段代码返回的是生成器,在 for 循环的时候 i 才实际增加,第二段代码返回的是数组,在 for 循环开始的时候 i 已经增加到 3 了 |
2 newmind Aug 23, 2018 第一个是括号(), 为生成器, 返回 generator 第二个是中括号[], 为列表生成式, 返回数组 |
3 HelloAmadeus Aug 23, 2018 ``` 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 Aug 23, 2018 ```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 Aug 23, 2018 via iPad 这不是 python 的问题。 我所知的语言里只有 erlang 不出这个问题 js 之类的一鸟样 |
6 cyrbuzz Aug 24, 2018 我比较好奇有什么情况下会用这样的写法。 |
7 ipwx Aug 24, 2018 |
8 whoami9894 Aug 24, 2018 via Android 补充一下,python 中只有 def,class,lambda 会产生作用域,所以这里 for 循环结束后 i 依然存在为 4,这里方括号列表解析生成的 lambda 可以看作是宏,所以会得到 6666 的结果 |
9 josephshen Aug 26, 2018 via iPhone 我告诉你上面的解释是出现了显现给的解释,原因根源是 python 这门语言的设计问题,导致了分不清申明和赋值 |
10 josephshen Aug 26, 2018 via iPhone 显示->现象 |
11 Alerta OP @HelloAmadeus 感谢感谢 一下子明白了 |