學習python有一段時間了,在學習過程中遇到很多難理解的東西,做一下總結,希望能對其他朋友有一些幫助。
完全是個人理解,難免有錯,歡迎其他大神朋友們批評指正。
1 迭代
什么是迭代呢??我們可以這樣理解,一個容器類型的數據,比如 列表[ ] 、元組 () 和 字典 { }, 我們可以把這樣類型的數據放入for temp in [1,2,3] 當中,temp 被一次一次的賦值成為后面容器內數據,然后我們拿到temp進行一些想做的事情。那么for 循環中自動的幫我們把數據一次一次的取出來,可以理解成,這樣的操作就是迭代。
2 可迭代對象
在python當中有有那么一些特定的數據類型,可以放入for in 循環當中,這樣的數據類型,我們可以說他們是可迭代對象。
我們可以用 isinstance方法來檢測一個對象是不是可迭代對象。
可迭代對象可以放入for in中迭代,也可以放入list() tuple()等幫我們快速生成一個數據。
上代碼!
1 from collections import Iterable 2
3 print( isinstance( [] , Iterable ) ) #True 4 print( isinstance( {} , Iterable ) ) #True 5 print( isinstance( () , Iterable ) ) #True 6 print( isinstance( 1 , Iterable ) ) #False
從中我們可以看出來,列表、元組、字典都是可迭代對象。而整型數據不是可迭代對象。
可迭代對象的實質是怎么回事呢???? (一臉懵逼)
其實,可迭代對象的內部必須實現一個方法,__iter__()方法,這個方法的功能是,返回一個迭代器,這個迭代器是幫助自己進行迭代的。實現這個方法的對象,python就認為它是可迭代對象。
迭代器又是啥???(二臉懵逼)不要着急 稍后我再分享
上代碼!!先看一看可迭代對象:
1 from collections import Iterable 2 #我們自己創建一個類 里面實現iter方法 python就認為它的對象是可迭代對象了
3 class MyIterableObj(object): 4 def __iter__(self): 5 pass
6
7 demo1 = MyIterableObj() 8 print(isinstance( demo1 , Iterable )) #True
從中可以看出來,我們自己寫一個類,里面實現了iter方法,即使什么都沒有做,創建一個對象之后,判斷一下 python就認為這個對象是一個可迭代對象了。
3 迭代器
剛剛我們說了,可迭代對象里面的iter方法返回一個幫助自己迭代的迭代器。迭代器是什么呢??
其實我也不知道!(嘻嘻 笑哭) 開玩笑的啦~~~
在我的理解當中呢,迭代器是幫助可迭代對象一個一個把里面元素取出來的一個對象。迭代器類型的對象都是可迭代對象,為什么呢,我們來看一看實質。
迭代器的實質:
迭代器內部必須實現兩個方法: __iter__() 和 __next__()
__iter__() 功能是返回一個迭代器,幫助我們自己這種類型進行迭代,因為自己就是迭代器,所以迭代器中的__iter__() 返回的是self自己
__next__() 功能是: 簡單的說就是返回當前元素的,就像列表當中,取出第一個元素,再調用next的時候就取出了第二個元素。 但是在for循環當中放入列表的時候,for是怎么知道列表最后一個元素都已經取完了呢????(我的天啊!不知道啊!!嗚嗚!!!)別着急,繼續往下看
復雜的說, next會做兩件事:1 如果當前數據沒有超出范圍,這次當前值返回,然后自己進行標記,找到下一個要返回的值。
2 如果當前迭代器上次取出了最后一個元素,這一次當前數據是在范圍之外的,那么就拋出異常(StopIteration),告訴for循環等一些內建工具,迭代結束了。
不是很理解??沒關系,上代碼我們來看看!!
我們先看一看 python中認為什么樣的東西是迭代器:
from collections import Iterator print( isinstance( [] , Iterator ) ) #False 很顯然,可迭代對象不是迭代器
print( isinstance( [].__iter__() , Iterator ) ) #True 這是調用了可迭代對象的iter方法得到一個迭代器對象 #在python中 內建了 iter() 方法和 next() 方法,把對象傳進去與__iter__ 和 __next__ 相同功能
print( isinstance( iter([]) , Iterator ) ) #True
# 像我說的 我們自己實現一個迭代器
class MyIterator(object): def __iter__(self): pass
def __next__(self): pass demo2 = MyIterator() print( isinstance(demo2 , Iterator ) ) # True
看的出來,我們自己的類對象里面只要具有這兩個方法 python就認為他是迭代器了。
大家還記不記得我說過,迭代器都是可迭代對象, 因為迭代器一定有__iter__方法,所以它一定是迭代對象
ok!接下來呢,我們把兩個函數的業務邏輯補全,看一看迭代器兩個方法實際上在干什么??
我們來實現一個 傳入一個n 給我們迭代出 0到n 的迭代器 這個功能就好像是 range(n) 一樣 我們自己實現一下!
1 ''' 2 接下來,我們具體實現一個能夠完成功能, 能夠放入for循環遍歷的迭代器!! 啊好刺激啊!! 3 我們要實現的業務是: 傳入一個參數n , 我們要迭代出 0到n的數 4 ''' 5 class NumIterator(object): 6 #初始化我們接收一個參數n 告訴我們迭代到多少結束 7 def __init__(self , n): 8 self.n = n 9 #我們實際上是把 i 交給函數調用者 10 self.i = 0 11 # iter方法 返回一個迭代器,自己就是迭代器 所以返回自己 12 def __iter__(self): 13 return self 14 # next方法 判斷是否越界 如果不越界返回一個元素 如果越界了拋出異常 15 def __next__(self): 16 #如果 沒有越界, 我們返回給調用者迭代結果,並且自己記錄下一次迭代的位置 17 if self.i <= self.n: 18 res = self.i 19 self.i += 1 20 return res 21 # 進入else說明i已經超過n 迭代越界了 拋出異常告訴for循環 迭代結束了 22 else: 23 #如果不拋出這個異常,for循環不知道什么時候停止迭代 會不停的調用next 陷入死循環 24 raise StopIteration 25 26 #一個前3的自然數的迭代器對象 27 demo3 = NumIterator(3) 28 # 之前說過, 我們可以調用python內建的next方法來獲取迭代器的元素 29 print( next(demo3) ) # 0 30 print( next(demo3) ) # 1 31 print( next(demo3) ) # 2 32 print( next(demo3) ) # 3 33 #print( next(demo3) ) # 這時候再調用會拋出異常 因為越界了! 34 35 #同樣我們自己寫的迭代器能夠放入for循環當中 36 demo4 = NumIterator(10) 37 for num in demo4 : 38 print(num) 39 #我們發現,會打印出從0 到 10 然后for循環就停了
看完上面的代碼,我來解釋一下 其實for循環的實質:
for 不知道我們放在in后面的是可迭代對象還是迭代器,他會先調用iter方法拿到一個迭代器,然后不停的調用next方法取到值,然后提供給我們,一直到取某個值的時候接收到了一個StopIteration異常,for循環就終止了。
ok!! 到這里呢,可迭代對象、迭代器的知識就跟大家分享完了。
不知道小伙伴們都有沒有理解,希望對一些不理解這些深層次東西的同學有一些幫助!!
歡迎大家批評指正~~~~謝謝大家的參考!
我是稀里糊塗的林老冷~