python當中的 可迭代對象 迭代器


學習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!! 到這里呢,可迭代對象、迭代器的知識就跟大家分享完了。

 

不知道小伙伴們都有沒有理解,希望對一些不理解這些深層次東西的同學有一些幫助!!

歡迎大家批評指正~~~~謝謝大家的參考!

我是稀里糊塗的林老冷~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM