关于廖雪峰老师filter教程中求素数详细理解


这是廖の码,用埃式筛法求得素数
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函数很配




免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM