最近在看廖雪峰的官网学习python,看到函数式编程的filter章节那里,作者给出了一个demo是关于用filter求素数。
文章连接在此处。点击打开链接
文中的代码是这样子的
filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
用filter求素数
首先,列出从2开始的所有自然数,构造一个序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,14, 15, 16, 17, 18, 19, 20, ...
取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15, 16, 17, 18, 19, 20, ...
取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19, 20, ...
取新序列的第一个数5,然后用5把序列的5的倍数筛掉:
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,18, 19, 20, ...
不断筛下去,就可以得到所有的素数。
以下贴出代码
def odd_iterator(): #构造一个从3开始的奇数序列,注意这是一个生成器,并且是一个无限序列。
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_iterator()# 初始序列
while True:
n = next(it)# 返回序列的第一个数
yield n
it = filter(not_divisible,it)# 构造新序列,<更改此处>
# 打印1000以内的素数:
for i in primes():
if i < 1000:
print(i)
else:
break
因为偷懒我把
it = filter(not_divisible, it)
更改成了这样
it = filter(lambda x: x % n != 0, it)
结果就出错了,想了好久,才记得这样是因为lambda有闭包,有关闭包的事情大家可以自行百度一下,我就不在这里说了。
这里我给大家一个更简单的例子体现闭包:
#生成一个0~9的list
l = [x for x in range(10)]
j = [x for x in range(10)]
def func(i):
return lambda x: x != i#筛选出与i不相同的数
for i in range(10):
j = filter(func, j)#不同处
for i in range(10):
l = filter(lambda x: x != i, l)#不同处
print(list(l))
print(list(j))
输出是
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
首先,按照我们的思维,程序应该生成一个[]空list,但是两个输出都不是,为什么呢?这里就关系到闭包的后期绑定了。
根据闭包的后期绑定,在for循环里,闭包只会保存循环最后一个数,也就是9。所以程序的实际生成的是筛选list里与9不相等的元素,因此才会生成如此结果。