新手求问,关于 lambda 表达式问题

2017-09-22 11:37:33 +08:00
 Jeepeng
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def main():
    for n in primes():
        if n < 100:
            print(n)
        else:
            break

def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n

def _not_divisible(n):
    return lambda x: x % n > 0

def primes():
    yield 2
    it = _odd_iter()
    while True:
        n = next(it)
        yield n
        it = filter(_not_divisible(n), it)

if __name__ == '__main__':
    main()

如果将

it = filter(_not_divisible(n), it)

改成

it = filter(lambda x: x % n > 0, it)

两次结果不一样,是 n 的作用域问题? filter 惰性求值问题?

3467 次点击
所在节点    Python
14 条回复
rwdy2008
2017-09-22 15:33:41 +08:00
首先说明下,题主的代码参数有点问题哦

其次,
_not_divisible 函数你这样写返回时的一个 function,function 永远是 True
直接写 lambda 返回的是 True 或者 False

filter 内置函数对 True 结果处理,这应该就是问题所在

最后,
看下面代码,题主参考下应该就明白了

def _not_divisible(n):
return lambda x: x % 3 > 0

filter(_not_divisible, [5,6])
[5, 6]

_not_divisible(5)
<function <lambda> at 0x036DAA30>
_not_divisible(6)
<function <lambda> at 0x036F82F0>

上面这两个都返回的是 function

filter(lambda x: x % 3 > 0, [5,6])
[5]

f = lambda x: x % 3 > 0
filter(f, [5,6])
[5]

f(5)
True
f(6)
False

这个有 False 返回

题主明白了吗?
rwdy2008
2017-09-22 15:34:36 +08:00
回复里不会贴代码,看起来有点乱,将就看吧,微笑脸
ballshapesdsd
2017-09-22 16:47:45 +08:00
@rwdy2008 你看错了
用了 python 好多年了,我也搞不懂,坐等高手,我感觉是不是跟下面这个有关:
1:
for i in range(5):
f=lambda x:x+i
i=5
print f(1)
output:
6
6
6
6
6

2:
def aaa(n):
return lambda x:x+n

for i in range(5):
f=aaa(i)
i=5
print f(1)
output:
1
2
3
4
5
ballshapesdsd
2017-09-22 17:06:29 +08:00
我觉得有可能是这样子的:
如果用 it = filter(lambda x: x % n > 0, it)的话,在使用 next(it)的时候,才会去找当前的 n,不管你之前过滤了多少次,等于用当前的 n 过滤了同样多次。
如果用 it = filter(_not_divisible(n), it)的话,会把每次过滤的 n 记录下来,所以就会成功输出所有素数了。
具体看上一层楼的例子。


应该只有这个解释了。
ballshapesdsd
2017-09-22 17:08:56 +08:00
如果用 it = filter(lambda x: x % n > 0, it)的话,比如说,next(it)要输出 5 的时候,会用 3 来过滤,如果 next(it)要输出 7 的话,就用 5 来过滤 2 次(当然和过滤 1 次一样),接下来输出 9,用 7 过滤,所以这样做等于把所有奇数都输出出来了。
wang9571
2017-09-22 17:17:57 +08:00
其实就是 1 楼说的问题
你改成 lambda n: lambda x: x % n > 0 试试
ballshapesdsd
2017-09-22 17:32:34 +08:00
@wang9571
什么鬼。。
kkzxak47
2017-09-22 17:32:45 +08:00
lambda 的返回值和 def 一样是个函数
khowarizmi
2017-09-22 20:23:18 +08:00
it 会形成嵌套的 generator,lambda 中 n 是引用(所以会变,都是同一个),而经过函数的 n 会被拷贝一份放闭包里。
Technetiumer
2017-09-22 20:55:34 +08:00
@rwdy2008 回复里可以 Gist
ManjusakaL
2017-09-22 22:20:06 +08:00
@khowarizmi 正解
Jeepeng
2017-09-22 23:08:48 +08:00
@rwdy2008
filter 第一个参数是函数,_not_divisible(n) 是函数, lambda x: x % n > 0 也是函数,这个参数没问题
Jeepeng
2017-09-22 23:12:32 +08:00
@wang9571
如果要这样改的话,应该改成:(lambda n: lambda x: x % n > 0)(n)
LeonHuayra
2017-09-22 23:25:52 +08:00
@khowarizmi 赞同使用函数形成闭包的解析。直接使用 lambda 表达式是无法形成闭包的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/392788

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX