Scu_laji

python filter

python filter + lambda

有个大佬来问了我一道有趣的问题(肯定是为学妹问的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/2/10 下午4:59
def _odd_iter():
z = 1
while True:
z = z + 2
yield z
def condition(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
it = filter(condtion(n), it)
for n in primes():
if (n < 1000):
print(n)
else:
break

上面的代码可以正常的输出 1000 以内的素数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/2/10 下午4:59
def _odd_iter():
z = 1
while True:
z = z + 2
yield z
def condition(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
it = filter(lambda x: x % n > 0, it)
for n in primes():
if (n < 1000):
print(n)
else:
break

但是这个就不行。

不信可以跑一下。

看着蛮简单的问题对吧。

这是我一开始的解释, 好像没啥问题。 其实大错特错。

python 的作用域是在当前作用域中没有找到,就会向上面的作用域进行寻找。

根本就没有问题啊,这是可以执行的, 其实原因出在 filter 上。

我们知道, filter 是一个生成器, 也就是说,它是惰性求值的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/2/10 下午4:59
def _odd_iter():
z = 1
while True:
z = z + 2
yield z
def condition(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
# print(lambda x:x %n > 0)
# print(condition(n))
it = filter(lambda x: x % n > 0, it)
if n > 10:
print("----------------")
i = 0
n = 13
for each in it:
print(each)
if i > 12:
break
i += 1
print("-----------------")
for n in primes():
if (n < 1000):
print(n)
else:
break

使用这段代码可以很好的说明这一情况。

当 yield 11 后

it = filter(lambda x: x % n > 0, it)
# n 等于11 大于10
# 这里为了控制输出长度, 特意只输出了10个
首先,我们把n的值赋值为13
然后进入for each in it:
这里filter才真正开始计算。
那么对于后者, 它在自己的作用域上没有找到n, 那么就跑到外面找,找到n = 13
然后以13做一次过滤,所以我们就没有看见13了。
那么为什么condition那个可以呢?
原因在于condition那个有一个n,它每次都保存了当时的n值,不用去寻找。