python3中用於過濾序列,過濾掉不符合條件的元素,返回乙個迭代器物件,如果要轉換為列表,可以使用list()來轉換。
廖雪峰關於filter的使用 很好的解釋了filter的作用,以及和生成器的結合,但是讓人疑惑的是:
it = filter(_not_divisible(n), it) #構造新序列
以上這段**的具體實現細節是什麼?it是個生成器,使用filter對其進行操作的時候,並沒有陷入無限迴圈,難道是對當前已生成的所有資料進行操作?那為什麼在9這個數的時候,又能被已經跳過的3給濾除?有可能是filter給原有的it新增了判斷規則,在生成9這個數的時候,自動執行filter規則?帶著這個疑問,在官網的文章中並沒有找到合理的解釋。但是發現如下**可以使用同樣的功能,給了更多的思考線索。
from itertools importfilte***lse
def_odd_iter():
n = 1
while
true:
n = n + 2
yield
n
def_not_divisible(n):
return
lambda x: x % n ==0
defprimes():
yield 2it = _odd_iter() #
初始序列
while
true:
n = next(it) #
返回序列的第乙個數
yield
n it = filte***lse(_not_divisible(n), it) #
構造新序列
#列印1000以內的素數:
for n in
primes():
if n < 1000:
(n)
else
:
break
上述**依舊能生成所有的素數,而關於filte***lse的原始碼如下所示:
deffilte***lse(predicate, iterable):
#filte***lse(lambda x: x%2, range(10)) --> 0 2 4 6 8
if predicate is
none:
predicate =bool
for x in
iterable:
ifnot
predicate(x):
yield x
這段**依舊讓人覺得費解,為什麼filte***lse沒有返回值,it感覺確實被賦了值,這個值就行是什麼?又做了如下實驗:
a = [1, 2, 3, 4, 5]a =iter(a)
b = filte***lse(lambda x: x%2==0, a)
(type(a))
(type(b))
(next(b))
(next(b))
(next(b))
輸出:'list_iterator
'>
'itertools.filte***lse
'>13
5
從中可以看出it是指向了itertools.filte***lse這個類的乙個例項,這個類是可迭代的,通過next(b)輸出了結果。b是生成器,a也是迭代器,在b的生成器函式裡使用迭代器a。
所以,原始**中filter重新賦值後的it是新的可迭代的型別,不是原始的生成器。就算是type(_odd_iter)也是,具有生成器功能的函式。
在primes迴圈while中,每次it會重新賦予乙個新的生成器,這個生成器巢狀了之前的生成器,是遞迴呼叫,最終的效果正如之前的猜想,相當於新增了規則,每次next的時候,對所有的規則遍歷一遍。具體的**執行是,每乙個生成器函式都儲存在記憶體中,乙個生成器函式又巢狀了上乙個生成器函式,每次next的時候,都會把之前所有的生成器函式遞迴一遍,等同於執行所有的規則。每執行一次訓練就會加一層巢狀,所有每次next的遍歷深度都在增加。
最後發現自己好蠢,it = filte***lse(_not_divisible(n), it) 這行**就是明顯的遞迴呼叫。
輸出:2
①it輸出:3
②it -> ①it
n=next(it) -> for x in ①iterable(相當於在原有生成器上執行了一次next) -> x=5,(判斷能被3整除嗎)yield 5
n=5輸出:5
③it -> ②it -> ①it
n=next(it) -> for x in ②iterable -> for x in ①iterable -> x=7,(判斷能被3整除嗎)yield 7 -> ②iterable -> x=7,(判斷能被5整除嗎)yield 7
n=7輸出:7
④ -> ③it -> ②it -> ①it
n=next(it) -> for x in ③iterable -> for x in ②iterable -> for x in ①iterable -> x=9 -> 能被3除去(沒有進入if,沒有執行yield,繼續for迴圈) -> x=11, (判斷能被3整除嗎)yield 11 -> ②iterable -> x=11, (判斷能被5除嗎)yield 11 -> ③iteable -> x=11, (判斷能被7整除嗎)yield 11
n=11
輸出:11
在遞迴呼叫中,yield相當於return,for x in iterable相當於呼叫巢狀函式。每次產生新的資料都是從最原始_odd_iter()產生,每返回一層,就進行一次if規則判斷,通過判斷就不斷向上層返回,不通過就再次向最底層遍歷。
posted @
2018-12-04 17:06
mjl_cv 閱讀(
...)
編輯收藏
filter函式與無限生成器結合使用遇到的問題
python3中用於過濾序列,過濾掉不符合條件的元素,返回乙個迭代器物件,如果要轉換為列表,可以使用list 來轉換。廖雪峰關於filter的使用 很好的解釋了filter的作用,以及和生成器的結合,但是讓人疑惑的是 it filter not divisible n it 構造新序列 以上這段 的...
函式與生成器
一 函式屬性 函式可以在內部建立預設的屬性,還可以在外部通過句點屬性識別符號來動態建立該函式的屬性。def foo foo properly created doc string def bar pass foo.doc foo properly created doc string bar.doc...
函式與生成器
一 函式 1.1 函式的關鍵字 def 定義函式 return 返回值 pass 佔位 exit 1 直接退出並返回1 1.2 高階函式 高階函式都是可以通過 邏輯實現,但是自己寫的函式的複雜程度或者演算法不一定有人家內建的好 map高階函式 def f x return x x print map...