這是廖の碼,用埃式篩法求得素數
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函數很配