这是廖の码,用埃式筛法求得素数
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)
for n in primes():
if n < 1000:
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
关于lambda,:之前的是输入,:之后的是输出,举几个例子
1.
c=lambda x:x*x
print(c(2))
输出为4
2.
c=lambda x:x%2>0
print(c(3))
输出为True
3.
c=lambda x:x%2>0
print(c(2))
输出为False
所以
def _not_divisible(n):
return lambda x: x % n > 0
这一段的意思是判断输入是否能被n整除,如果被整除那么这个输入就不是素数
接下来一段
def primes():
yield 2#输出第一个素数2
it = _odd_iter() # 初始序列,it是一个生成器
while True:
n = next(it) # 返回序列的第一个数
yield n
it= filter(_not_divisible(n),it)
说这段之前,先了解一下这段中的it,是一个generator object,生成器可以理解为一个空间,每次next调用这个空间中原有的值会被覆盖
一开始it中没有值,第一次next(it),it中变为3,第二次next变为5
了解一下filter,在filter前面没有一个list时,即不是list(filter(...,...))时,filter只是一个filter generator 类似于生成器
也就是说it= filter(_not_divisible(n),it)这段代码其实是把it变为了filter object,但因为没有next,并不会进行筛选
接下来通过单步调试来解释具体运行过程,
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)
for n in primes():
if n < 1000:
print(n)
else:
break
从for n in primes():这一行开始调试(建议一边打开pc调试一边对照)
1.进入primes()
2.yield 2,然后n<1000,输出2
3.it=_odd_iter() #it为generator object
4.进入while循环,n=next(it)
5.进入到_odd_iter()函数,出来时n=3,可理解为it=[3]
6.yield n
7.if n<1000,print(n)#输出3
8.it'= filter(_not_divisible(n),it) #这里it变为了一个filter object,同样没有next和list(filter...),filter不进行筛选功能
这行代码类似于
it'= filter(_not_divisible(n),[3])
为表达清楚,对多个it的先后出现顺序以'的多少表示。为表达清楚,对多个it的先后出现顺序以'的多少表示。为表达清楚,对多个it的先后出现顺序以'的多少表示
9.进入_not_divisible()函数,确定n为3
10.n=next(it),此时it是filter object,开始执行filter的过滤,也就是说
it'= filter(_not_divisible(n),it)这段代码的过滤真正执行
11.进入_odd_iter()中,
为什么跳到_odd_iter()中,因为
it'= filter(_not_divisible(n),it),it是生成器,所以先对it进行next
12.跳出_odd_iter后,n=5
可理解为it=[5]
13.进入_not_divisible(),需要接受x
14.此时it'过滤完成,具体表现出来为it=filter(_not_divisible(3),[5])
5%3>0,所以n=5
然后5<1000,输出5后,进入15步骤
15.it''=filter(_not_divisible(),it']#这一步关键,可理解成为it''=filter(_not_divisible(),filter(_not_divisible(n),it)]
16.进入_not_divisible()函数,确定n为5
17.n=next(it)
18.进入_odd_iter() #出来后it=[7]
19.执行it''=filter(_not_divisible(n'),filter(_not_divisible(n),it)]中的原it位置,也就是filter(_not_divisible(n),it),即
filter(_not_divisible(3),[7]),
整句话翻译一下就是
it''=filter(_not_divisible(5),filter(_not_divisible(3),[7]))
意思就是7先对3,再对5整除
调试到这里,大体思路就已经明了了,利用无限序列生成奇数,再对这个生成的奇数判断是否被3,5,7,11,13......(即之前的素数)整除,这个运行的方式看起来和埃式筛法不太像,导致一开始理解不能
总结一下几个知识点:
1.filter和generator类似,在没有next()情况下,不真正执行
2.若多次用x=filter(.....,x)这种形式表示的话,filter会嵌套执行,会递归
3.gennerator object每次next后会覆盖原来值
4.lambda函数与filter函数很配