什么是迭代器汇荐,Python迭代器及其用法

前面章節(jié)中,已經(jīng)對列表(list)盆繁、元組(tuple)掀淘、字典(dict)、集合(set)這些序列式容器做了詳細的介紹油昂。值得一提的是革娄,這些序列式容器有一個共同的特性,它們都支持使用 for 循環(huán)遍歷存儲的元素冕碟,都是可迭代的拦惋,因此它們又有一個別稱,即迭代器安寺。

從字面來理解厕妖,迭代器指的就是支持迭代的容器,更確切的說挑庶,是支持迭代的容器類對象言秸,這里的容器可以是列表软能、元組等這些 Python 提供的基礎容器,也可以是自定義的容器類對象举畸,只要該容器支持迭代即可埋嵌。

Python實現(xiàn)自定義序列》一節(jié)中,已經(jīng)學會了如何自定義一個序列類俱恶,但該序列類對象并不支持迭代雹嗦,因此還不能稱之為迭代器。如果要自定義實現(xiàn)一個迭代器合是,則類中必須實現(xiàn)如下 2 個方法:

  1. next(self):返回容器的下一個元素了罪。
  2. iter(self):該方法返回一個迭代器(iterator)。

例如聪全,下面程序自定義了一個簡易的列表容器迭代器泊藕,支持迭代:

<pre class="python sh_python snippet-formatted sh_sourceCode" style="margin: 0px; display: block; padding: 0px; font-size: 14px; line-height: 1.6em; color: rgb(102, 102, 102); white-space: pre-wrap; overflow-wrap: break-word; background: none; border: none; border-radius: 0px;">

1.  class listDemo:
2.  def __init__(self):
3.  self.__date=[]
4.  self.__step = 0
5.  def __next__(self):
6.  if self.__step <= 0:
7.  raise StopIteration
8.  self.__step -= 1
9.  #返回下一個元素
10.  return self.__date[self.__step]
11.  def __iter__(self):
12.  #實例對象本身就是迭代器對象,因此直接返回 self 即可
13.  return self
14.  #添加元素
15.  def __setitem__(self,key,value):
16.  self.__date.insert(key,value)
17.  self.__step += 1
18.  mylist = listDemo()
19.  mylist[0]=1
20.  mylist[1]=2
21.  for i in mylist:
22.  print (i)

</pre>

程序執(zhí)行結果為:

2
1

除此之外难礼,Python 內(nèi)置的 iter() 函數(shù)也會返回一個迭代器娃圆,該函數(shù)的語法格式如下:

iter(obj[, sentinel])

其中,obj 必須是一個可迭代的容器對象蛾茉,而 sentinel 作為可選參數(shù)讼呢,如果使用此參數(shù),要求 obj 必須是一個可調(diào)用對象谦炬,具體功能后面會講悦屏。

可調(diào)用對象,指的是該類的實例對象可以像函數(shù)那樣键思,直接以“對象名()”的形式被使用础爬。通過在類中添加 call() 方法,就可以將該類的實例對象編程可調(diào)用對象吼鳞。有關 call() 方法看蚜,可閱讀《Python call()》做詳細了解。

我們常用的是僅有 1 個參數(shù)的 iter() 函數(shù)赔桌,通過傳入一個可迭代的容器對象供炎,我們可以獲得一個迭代器,通過調(diào)用該迭代器中的 next() 方法即可實現(xiàn)迭代纬乍。例如碱茁;

<pre class="python sh_python snippet-formatted sh_sourceCode" style="margin: 0px; display: block; padding: 0px; font-size: 14px; line-height: 1.6em; color: rgb(102, 102, 102); white-space: pre-wrap; overflow-wrap: break-word; background: none; border: none; border-radius: 0px;">

1.  # 將列表轉(zhuǎn)換為迭代器
2.  myIter = iter([1, 2, 3])
3.  # 依次獲取迭代器的下一個元素
4.  print(myIter.__next__())
5.  print(myIter.__next__())
6.  print(myIter.__next__())
7.  print(myIter.__next__())

</pre>

運行結果為:

Traceback (most recent call last):
File "C:\Users\mengma\Desktop\demo.py", line 7, in <module>
print(myIter.next())
StopIteration

另外,也可以使用 next() 內(nèi)置函數(shù)來迭代仿贬,即 next(myIter),和 next() 方法是完全一樣的墓贿。

從程序的執(zhí)行結果可以看出茧泪,當?shù)甏鎯Φ乃性刂篁寻保绻^續(xù)迭代,則 next() 方法會拋出 StopIteration 異常队伟。

這里介紹 iter() 函數(shù)第 2 個參數(shù)的作用穴吹,如果使用該參數(shù),則要求第一個 obj 參數(shù)必須傳入可調(diào)用對象(可以不支持迭代)嗜侮,這樣當使用返回的迭代器調(diào)用 next() 方法時港令,它會通過執(zhí)行 obj() 調(diào)用 call() 方法,如果該方法的返回值和第 2 個參數(shù)值相同锈颗,則輸出 StopInteration 異常顷霹;反之,則輸出 call() 方法的返回值击吱。

例如淋淀,修改 listDemo 類如下所示:

<pre class="python sh_python snippet-formatted sh_sourceCode" style="margin: 0px; display: block; padding: 0px; font-size: 14px; line-height: 1.6em; color: rgb(102, 102, 102); white-space: pre-wrap; overflow-wrap: break-word; background: none; border: none; border-radius: 0px;">

1.  class listDemo:
2.  def __init__(self):
3.  self.__date=[]
4.  self.__step = 0

6.  def __setitem__(self,key,value):
7.  self.__date.insert(key,value)
8.  self.__step += 1
9.  #是該類實例對象成為可調(diào)用對象
10.  def __call__(self):
11.  self.__step-=1
12.  return self.__date[self.__step]

14.  mylist = listDemo()
15.  mylist[0]=1
16.  mylist[1]=2
17.  #將 mylist 變?yōu)榈?18.  a = iter(mylist,1)
19.  print(a.__next__())
20.  print(a.__next__())

</pre>

程序執(zhí)行結果為:

Traceback (most recent call last):
File "D:\python3.6\1.py", line 20, in <module>
print(a.next())
StopIteration

輸出結果中,之所以最終拋出 StopIteration 異常覆醇,是因為這里原本要輸出的元素 1 和 iter() 函數(shù)的第 2 個參數(shù)相同朵纷。

迭代器本身是一個底層的特性和概念,在程序中并不常用永脓,但它為生成器這一更有趣的特性提供了基礎袍辞。有關生成器的相關知識,會在后續(xù)章節(jié)中介紹常摧。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末革屠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子排宰,更是在濱河造成了極大的恐慌似芝,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件板甘,死亡現(xiàn)場離奇詭異党瓮,居然都是意外死亡,警方通過查閱死者的電腦和手機盐类,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門寞奸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人在跳,你說我怎么就攤上這事枪萄。” “怎么了猫妙?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵瓷翻,是天一觀的道長。 經(jīng)常有香客問我,道長齐帚,這世上最難降的妖魔是什么妒牙? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮对妄,結果婚禮上湘今,老公的妹妹穿的比我還像新娘。我一直安慰自己剪菱,他們只是感情好摩瞎,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著孝常,像睡著了一般旗们。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茫因,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天蚪拦,我揣著相機與錄音,去河邊找鬼冻押。 笑死驰贷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的洛巢。 我是一名探鬼主播括袒,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼稿茉!你這毒婦竟也來了锹锰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤漓库,失蹤者是張志新(化名)和其女友劉穎恃慧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渺蒿,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡痢士,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了茂装。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怠蹂。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖少态,靈堂內(nèi)的尸體忽然破棺而出城侧,到底是詐尸還是另有隱情,我是刑警寧澤彼妻,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布嫌佑,位于F島的核電站豆茫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏歧强。R本人自食惡果不足惜澜薄,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一为肮、第九天 我趴在偏房一處隱蔽的房頂上張望摊册。 院中可真熱鬧,春花似錦颊艳、人聲如沸茅特。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽白修。三九已至,卻和暖如春重斑,著一層夾襖步出監(jiān)牢的瞬間兵睛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工窥浪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祖很,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓漾脂,卻偏偏與公主長得像假颇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子骨稿,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容