最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Python中的可迭代對(duì)象、迭代器、For循環(huán)工作機(jī)制、生成器

 更新時(shí)間:2019年03月11日 09:41:59   作者:急速奔跑的蝸牛  
這篇文章主要介紹了Python中的可迭代對(duì)象、迭代器、For循環(huán)工作機(jī)制、生成器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1.iterable iterator區(qū)別

要了解兩者區(qū)別,先要了解一下迭代器協(xié)議:
迭代器協(xié)議是指:對(duì)象需要提供__next__()方法,它返回迭代中的元素,在沒有更多元素后,拋出StopIteration異常,終止迭代。
可迭代對(duì)象就是:實(shí)現(xiàn)了迭代器協(xié)議的對(duì)象。
協(xié)議是一種約定,可迭代對(duì)象實(shí)現(xiàn)迭代器協(xié)議,Python的內(nèi)置工具(如for循環(huán),sum,min,max函數(shù)等)通過迭代器協(xié)議訪問對(duì)象,因此,for循環(huán)并不需要知道對(duì)象具體是什么,只需要知道對(duì)象能夠?qū)崿F(xiàn)迭代器協(xié)議即可。
迭代器(iterator)與可迭代對(duì)象(iterable)并不是同一個(gè)概念。

直觀上:

1.可迭代對(duì)象(iterable):凡是具有__iter__的方法的類,都是可迭代的類。可迭代類創(chuàng)建的對(duì)象實(shí)現(xiàn)了__iter__方法,因此就是可迭代對(duì)象。用list、tuple等容器創(chuàng)建的對(duì)象,都是可迭代對(duì)象。可迭代對(duì)象通過__iter__方法返回一個(gè)迭代器,然后在內(nèi)部調(diào)用__next__方法進(jìn)行迭代,最后沒有元素時(shí),拋出異常(這個(gè)異常python自己會(huì)處理,不會(huì)讓開發(fā)者看見)。

2.迭代器(iterator):迭代器對(duì)象必須同時(shí)實(shí)現(xiàn)__iter__和__next__方法才是迭代器。對(duì)于迭代器來說,__iter__ 返回的是它自身 self,__next__ 則是返回迭代器中的下一個(gè)值,最后沒有元素時(shí),拋出異常(異??梢员婚_發(fā)者看到)。

從上面2點(diǎn)可以看出:

1.迭代器一定是可迭代對(duì)象,因?yàn)樗鼘?shí)現(xiàn)了__iter__()方法;

2.通過iter()方法(在類的內(nèi)部就是__iter__)能夠使一個(gè)可迭代對(duì)象返回一個(gè)迭代器。

3.迭代器的 __iter__ 方法返回的是自身,并不產(chǎn)生新的迭代器對(duì)象。而可迭代對(duì)象的 __iter__ 方法通常會(huì)返回一個(gè)新的迭代器對(duì)象。

第3點(diǎn)性質(zhì)正是可迭代對(duì)象可以重復(fù)遍歷的原因(每次返回一個(gè)獨(dú)立的迭代器,就可以保證不同的迭代過程不會(huì)互相影響);而迭代器由于返回自身,因此只能遍歷一次。

上面3點(diǎn)可以通過下面的例子看出來:

from collections import Iterable
from collections import Iterator
print isinstance(iter([1,2]),Iterator)
print isinstance(iter([1,2]),Iterable)
print isinstance([1,2],Iterator)
print isinstance([1,2],Iterable)
##result
True
True
False
True
##id可以查看一個(gè)對(duì)象在內(nèi)存中的地址
test=[1,2,3]
testIter=iter(test)
print id(testIter)
print id(testIter)
print id(iter(test))
print id(iter(test))
print id(test.__iter__())
print id(test.__iter__())
##result:可迭代對(duì)象每次調(diào)用iter方法都會(huì)返回一個(gè)新的迭代器對(duì)象,而迭代器對(duì)象調(diào)用iter方法返回自身
67162576 
67162576 
67162688 
67162632 
67162856 
67163024

2.iterable的工作機(jī)制

拿一個(gè)例子看看,首先定義一個(gè)有__iter__方法,但是沒有next()方法的類 (PS:在python2中是next(),python3是__next__()):

from collections import Iterable, Iterator
class Student(object):
 def __init__(self,score):
 self.score=score
 def __iter__(self):
 return iter(self.score)
 
test= Student([80,90,95])
print isinstance(test, Iterable)
print isinstance(test, Iterator)
for i in test:
 print i
##result
True
False
80
90
95
##可重復(fù)遍歷
for i in test:
 print i
##result
80
90
95

上面代碼的結(jié)果印證了定義中提到的:

缺少了next()方法,可迭代對(duì)象就不是迭代器。

此外,注意到:可迭代對(duì)象通過__iter__方法每次都返回了一個(gè)獨(dú)立的迭代器,這樣就可以保證不同的迭代過程不會(huì)互相影響。

也就是說,通過iterable可以實(shí)現(xiàn)重復(fù)遍歷,而迭代器是無法重復(fù)遍歷的!

因此,如果想要把可迭代對(duì)象轉(zhuǎn)變?yōu)榈?,可以先調(diào)用iter()方法返回一個(gè)迭代器。然后就可以用next()不斷迭代了!

print isinstance(iter(test),Iterator)
testIter=iter(test)
print testIter.next()
print testIter.next()
print testIter.next()
##result
True
80
90
95
##一旦取完了可迭代對(duì)象中所有的元素,再次調(diào)用next就會(huì)發(fā)生異常
print testIter.next()
##result
StopIteration: 

3.迭代器Iterator的工作機(jī)制

看下面這個(gè)例子:

class Student(object):
 def __init__(self,score):
 self.score=score
 def __iter__(self):
 return self
 
 def next(self):
 if self.score<100:
 self.score+=1
 return self.score
 else:
 raise StopIteration()
 
test= Student(90)
print isinstance(test, Iterable)
print isinstance(test, Iterator)
print test.next()
print test.next()
print test.next()
for i in test:
 print i
##result
True
True
91
92
93
94
95
96
97
98
99
100
##如果此時(shí)再對(duì)test這個(gè)迭代器調(diào)用next方法,就會(huì)拋出異常
test.next()
##result
StopIteration: 

這個(gè)例子印證了定義中的:迭代器對(duì)象必須同時(shí)實(shí)現(xiàn)__iter__和__next__方法才是迭代器。

那么,使用迭代器好處在哪呢?

Python的Iterator對(duì)象表示的是一個(gè)數(shù)據(jù)流,Iterator對(duì)象可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤??梢园堰@個(gè)數(shù)據(jù)流看做是一個(gè)有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數(shù)實(shí)現(xiàn)按需計(jì)算下一個(gè)數(shù)據(jù),所以Iterator的計(jì)算是惰性的,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算。

一個(gè)很常見的應(yīng)用就是:Python在處理列表的時(shí)候,是直接把整個(gè)列表讀進(jìn)內(nèi)存的,當(dāng)遇到大量樣本時(shí)的時(shí)候會(huì)變得很慢。而迭代器的優(yōu)勢(shì)在于只把需要的元素讀進(jìn)內(nèi)存,因此占用內(nèi)存更少。

換句話說,迭代器是一種惰性求值模式,它是有狀態(tài)的,只有在調(diào)用時(shí)才返回值,沒有調(diào)用的時(shí)候就等待下一次調(diào)用。這樣就節(jié)省了大量內(nèi)存空間。

這個(gè)例子印證了定義中的:迭代器對(duì)象必須同時(shí)實(shí)現(xiàn)__iter__和__next__方法才是迭代器。

那么,使用迭代器好處在哪呢?

Python的Iterator對(duì)象表示的是一個(gè)數(shù)據(jù)流,Iterator對(duì)象可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤??梢园堰@個(gè)數(shù)據(jù)流看做是一個(gè)有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數(shù)實(shí)現(xiàn)按需計(jì)算下一個(gè)數(shù)據(jù),所以Iterator的計(jì)算是惰性的,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算。

一個(gè)很常見的應(yīng)用就是:Python在處理列表的時(shí)候,是直接把整個(gè)列表讀進(jìn)內(nèi)存的,當(dāng)遇到大量樣本時(shí)的時(shí)候會(huì)變得很慢。而迭代器的優(yōu)勢(shì)在于只把需要的元素讀進(jìn)內(nèi)存,因此占用內(nèi)存更少。

換句話說,迭代器是一種惰性求值模式,它是有狀態(tài)的,只有在調(diào)用時(shí)才返回值,沒有調(diào)用的時(shí)候就等待下一次調(diào)用。這樣就節(jié)省了大量內(nèi)存空間。

4.for循環(huán)的工作機(jī)制

有了上面2個(gè)例子,就可以總結(jié)一下在可迭代對(duì)象與迭代器中的For循環(huán)工作機(jī)制了。

當(dāng)對(duì)象本身就是迭代器時(shí),F(xiàn)or循環(huán)工作機(jī)制:

  1. 調(diào)用 __iter__方法,返回自身self,也就是返回迭代器。
  2. 不斷地調(diào)用迭代器的next()方法,每次按序返回迭代器中的一個(gè)值。
  3. 迭代到最后沒有元素時(shí),就拋出異常 StopIteration

在可迭代對(duì)象中,for循環(huán)工作機(jī)制:

  1. 先判斷對(duì)象是否為可迭代對(duì)象(等價(jià)于判斷有沒有__iter__或__getitem__方法),沒有的話直接報(bào)錯(cuò),拋出TypeError異常。有的話,調(diào)用 __iter__方法,返回一個(gè)迭代器。
  2. 在python內(nèi)部不斷地調(diào)用迭代器的__next__方法,每次按序返回迭代器中的一個(gè)值。
  3. 迭代到最后沒有元素時(shí),就拋出異常 StopIteration,這個(gè)異常 python 自己會(huì)處理,不會(huì)暴露給開發(fā)者。

借用網(wǎng)絡(luò)上的一張圖直觀理解一下:

此外,還要注意,python中的for循環(huán)其實(shí)兼容了兩種機(jī)制:

  1. 如果對(duì)象有__iter__會(huì)返回一個(gè)迭代器。
  2. 如果對(duì)象沒有__iter__,但是實(shí)現(xiàn)了__getitem__,會(huì)改用下標(biāo)迭代的方式。
  3. __getitem__可以幫助一個(gè)對(duì)象進(jìn)行取數(shù)和切片操作。

當(dāng)for發(fā)現(xiàn)沒有__iter__但是有__getitem__的時(shí)候,會(huì)從0開始依次讀取相應(yīng)的下標(biāo),直到發(fā)生IndexError為止,這是一種舊的迭代協(xié)議。iter方法也會(huì)處理這種情況,在不存在__iter__的時(shí)候,返回一個(gè)下標(biāo)迭代的iterator對(duì)象來代替。一個(gè)重要的例子是str,字符串就是沒有__iter__方法的,但是卻依然可以迭代,原因就是其在for循環(huán)時(shí)調(diào)用了__getitem__方法。

看一個(gè)例子:

from collections import Iterable, Iterator
class Student(object):
 def __init__(self,score):
 self.score=score
 def __getitem__(self,n):
 return self.score[n]
 
test= Student([80,90,95])
print isinstance(test, Iterable)
print isinstance(test, Iterator)
print isinstance(iter(test), Iterable)
print isinstance(iter(test), Iterator)
for i in test:
 print i
##result
False
False
True
True
80
90
95
for i in range(0,3):
 print test[i]
##result
80
90
95
for i in iter(test):
 print i
##result
80
90
95

可以看到,實(shí)現(xiàn)了__getitem__方法的對(duì)象本身,盡管不是iterable與iterator,仍舊是可以調(diào)用for循環(huán)的。
通過iter方法,返回一個(gè)下標(biāo)迭代的iterator對(duì)象。

5.generator的原理

最后說一下生成器,生成器是一種特殊的迭代器,當(dāng)然也是可迭代對(duì)象。
對(duì)于生成器,Python會(huì)自動(dòng)實(shí)現(xiàn)迭代器協(xié)議,以便應(yīng)用到迭代中(如for循環(huán),sum函數(shù))。由于生成器自動(dòng)實(shí)現(xiàn)了迭代器協(xié)議,所以,我們可以調(diào)用它的next方法,并且,在沒有值可以返回的時(shí)候,生成器自動(dòng)產(chǎn)生StopIteration異常。
創(chuàng)建生成器的方法:將return 改為yield。具體的實(shí)現(xiàn)網(wǎng)絡(luò)上教程很多,不細(xì)說了。

6.總結(jié)

到一幅圖片很好的描述了本文的所有內(nèi)容,就拿它作為文末的總結(jié)吧!

以上所述是小編給大家介紹的Python中的可迭代對(duì)象、迭代器、For循環(huán)工作機(jī)制、生成器詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 深入理解NumPy簡明教程---數(shù)組3(組合)

    深入理解NumPy簡明教程---數(shù)組3(組合)

    本篇文章對(duì)NumPy數(shù)組進(jìn)行較深入的探討。首先介紹自定義類型的數(shù)組,接著數(shù)組的組合,最后介紹數(shù)組復(fù)制方面的問題,有興趣的可以了解一下。
    2016-12-12
  • wxPython色環(huán)電阻計(jì)算器

    wxPython色環(huán)電阻計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了wxPython色環(huán)電阻計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 關(guān)于pandas-profiling的降級(jí)之旅

    關(guān)于pandas-profiling的降級(jí)之旅

    這篇文章主要介紹了關(guān)于pandas-profiling的降級(jí)之旅,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Python for循環(huán)搭配else常見問題解決

    Python for循環(huán)搭配else常見問題解決

    這篇文章主要介紹了Python for循環(huán)搭配else常見問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • python使用bs4爬取boss直聘靜態(tài)頁面

    python使用bs4爬取boss直聘靜態(tài)頁面

    這篇文章主要介紹了python如何使用bs4爬取boss直聘靜態(tài)頁面,幫助大家更好的理解和學(xué)習(xí)爬蟲,感興趣的朋友可以了解下
    2020-10-10
  • 基于Python制作ASCII碼轉(zhuǎn)換器

    基于Python制作ASCII碼轉(zhuǎn)換器

    ASCII碼是基于拉丁字母的一套電腦編碼系統(tǒng),主要用于顯示現(xiàn)代英語和其他西歐語言。本文將利用Python制作一個(gè)ASCII碼轉(zhuǎn)換器,感興趣的可以動(dòng)手試一試
    2022-02-02
  • 不管你的Python報(bào)什么錯(cuò),用這個(gè)模塊就能正常運(yùn)行

    不管你的Python報(bào)什么錯(cuò),用這個(gè)模塊就能正常運(yùn)行

    說到python強(qiáng)大的地方,那真是太多了,優(yōu)雅、簡潔、豐富且強(qiáng)大的第三方庫,開發(fā)速度快,活躍度高等,本文講到的就是其中一個(gè)模塊,用了它,再也不用擔(dān)心代碼不能運(yùn)行了
    2018-09-09
  • Python實(shí)現(xiàn)arctan換算角度的示例

    Python實(shí)現(xiàn)arctan換算角度的示例

    本文主要介紹了Python實(shí)現(xiàn)arctan換算角度的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • python中退出多層循環(huán)的方法

    python中退出多層循環(huán)的方法

    這篇文章主要介紹了python中退出多層循環(huán)的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • 解決python 讀取 log日志的編碼問題

    解決python 讀取 log日志的編碼問題

    今天小編就為大家分享一篇解決python 讀取 log日志的編碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12

最新評(píng)論

深泽县| 廊坊市| 满洲里市| 安泽县| 黎城县| 赫章县| 天全县| 米易县| 临城县| 方正县| 苍梧县| 肇州县| 盐津县| 三门峡市| 卓尼县| 金沙县| 岳普湖县| 乡宁县| 宁津县| 云梦县| 陵水| 岐山县| 龙川县| 饶阳县| 乡城县| 堆龙德庆县| 睢宁县| 沂源县| 裕民县| 安泽县| 井陉县| 上蔡县| 东莞市| 依安县| 阳信县| 遵化市| 太康县| 辛集市| 白沙| 吴旗县| 惠水县|