1、什麼叫疊代
現在,我們已經獲得了一個新線索,有一個叫做“可疊代的”概念。
首先,我們從報錯來分析,好像之是以1234不可以for循環,是因為它不可疊代。那麼如果“可疊代”,就應該可以被for循環了。
這個我們知道呀,字元串、清單、元組、字典、集合都可以被for循環,說明他們都是可疊代的。
我們怎麼來證明這一點呢?
1 from collections importIterable2
3 l = [1,2,3,4]4 t = (1,2,3,4)5 d = {1:2,3:4}6 s = {1,2,3,4}7
8 print(isinstance(l,Iterable))9 print(isinstance(t,Iterable))10 print(isinstance(d,Iterable))11 print(isinstance(s,Iterable))
結合我們使用for循環取值的現象,再從字面上了解一下,其實疊代就是我們剛剛說的,可以将某個資料集内的資料“一個挨着一個的取出來”,就叫做疊代。
2、疊代器和協定
既什麼叫“可疊代”之後,又一個曆史新難題,什麼叫“疊代器”?
雖然我們不知道什麼叫疊代器,但是我們現在已經有一個疊代器了,這個疊代器是一個清單的疊代器。
我們來看看這個清單的疊代器比起清單來說實作了哪些新方法,這樣就能揭開疊代器的神秘面紗了吧?
1 '''
2 dir([1,2].__iter__())是清單疊代器中實作的所有方法,dir([1,2])是清單中實作的所有方法,都是以清單的形式傳回給我們的,為了看的更清楚,我們分别把他們轉換成集合,3 然後取差集。4 '''
5 #print(dir([1,2].__iter__()))
6 #print(dir([1,2]))
7 print(set(dir([1,2].__iter__()))-set(dir([1,2])))8
9 結果:10 {'__length_hint__', '__next__', '__setstate__'}11
12
13 iter_l = [1,2,3,4,5,6].__iter__()14 #擷取疊代器中元素的長度
15 print(iter_l.__length_hint__())16 #根據索引值指定從哪裡開始疊代
17 print('*',iter_l.__setstate__(4))18 #一個一個的取值
19 print('**',iter_l.__next__())20 print('***',iter_l.__next__())
這三個方法中,能讓我們一個一個取值的神奇方法是誰?
沒錯!就是__next__
在for循環中,就是在内部調用了__next__方法才能取到一個一個的值。
那接下來我們就用疊代器的next方法來寫一個不依賴for的周遊。
1 l = [1,2,3,4]2 l_iter = l.__iter__()3 item = l_iter.__next__()4 print(item)5 item = l_iter.__next__()6 print(item)7 item = l_iter.__next__()8 print(item)9 item = l_iter.__next__()10 print(item)11 item = l_iter.__next__()12 print(item)
這是一段會報錯的代碼,如果我們一直取next取到疊代器裡已經沒有元素了,就會抛出一個異常StopIteration,告訴我們,清單中已經沒有有效的元素了。
這個時候,我們就要使用異常處理機制來把這個異常處理掉。
1 l = [1,2,3,4]2 l_iter = l.__iter__()3 whileTrue:4 try:5 item = l_iter.__next__()6 print(item)7 exceptStopIteration:8 break
3、可疊代對象
我們現在是從結果分析原因,能被for循環的就是“可疊代的”,但是如果正着想,for怎麼知道誰是可疊代的呢?
假如我們自己寫了一個資料類型,希望這個資料類型裡的東西也可以使用for被一個一個的取出來,那我們就必須滿足for的要求。這個要求就叫做“協定”。
可以被疊代要滿足的要求就叫做可疊代協定。可疊代協定的定義非常簡單,就是内部實作了__iter__方法。
疊代器生成的對象就是可疊代對象
4、生成器
Python中提供的生成器:
1.生成器函數:正常函數定義,但是,使用yield語句而不是return語句傳回結果。yield語句一次傳回一個結果,在每個結果中間,挂起函數的狀态,以便下次重它離開的地方繼續執行
2.生成器表達式:類似于清單推導,但是,生成器傳回按需産生結果的一個對象,而不是一次建構一個結果清單
生成器Generator:
本質:疊代器(是以自帶了__iter__方法和__next__方法,不需要我們去實作)
特點:惰性運算,開發者自定義
1 importtime2 defgenrator_fun1():3 a = 1
4 print('現在定義了a變量')5 yielda6 b = 2
7 print('現在又定義了b變量')8 yieldb9
10 g1 =genrator_fun1()11 print('g1 :',g1) #列印g1可以發現g1就是一個生成器
12 print('-'*20) #我是華麗的分割線
13 print(next(g1))14 time.sleep(1) #sleep一秒看清執行過程
15 print(next(g1))
1 defgenerator():2 print(123)3 content = yield 1
4 print('=======',content)5 print(456)6 yield27
8 g =generator()9 ret = g.__next__()10 print('***',ret)11 ret = g.send('hello') #send的效果和next一樣
12 print('***',ret)13
14 #send 擷取下一個值的效果和next基本一緻
15 #隻是在擷取下一個值的時候,給上一yield的位置傳遞一個資料
16 #使用send的注意事項
17 #第一次使用生成器的時候 是用next擷取下一個值
18 #最後一個yield不能接受外部的值
1 #yield from
2
3 defgen1():4 for c in 'AB':5 yieldc6 for i in range(3):7 yieldi8
9 print(list(gen1()))10
11 defgen2():12 yield from 'AB'
13 yield from range(3)14
15 print(list(gen2()))16
17 yield from