關於廖雪峰老師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