成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python迭代器資料整理

Muninn / 3483人閱讀

摘要:滿足以上要求的對(duì)象,就是迭代器。其中,必需返回一個(gè)迭代器對(duì)象,則負(fù)責(zé)迭代邏輯并在迭代完畢時(shí)觸發(fā)異常??梢栽诒闅v迭代器的時(shí)候,加入一個(gè)判斷語句,避免無法多次迭代的情況發(fā)生參考資料官網(wǎng)迭代器文檔

什么是迭代器 相關(guān)概念定義 迭代器(Iterator):

滿足迭代協(xié)議的對(duì)象就是迭代器
iterator就是實(shí)現(xiàn)了Iteration Protocol的對(duì)象,這類對(duì)象都支持循環(huán)遍歷的操作(for/while/支持迭代的函數(shù)list() sum()...)。

迭代協(xié)議(Iteration Protocol):

內(nèi)建函數(shù)iter()接收一個(gè)可迭代對(duì)象,并返回一個(gè)可迭代對(duì)象.
每次將這個(gè)可迭代對(duì)象傳遞給next()函數(shù),都會(huì)返回它所包含的下一個(gè)元素,當(dāng)?shù)曜詈笠粋€(gè)元素時(shí),就會(huì)觸發(fā)StopIteration異常。

>>> x = iter([1, 2, 3])
>>> x

>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> next(x)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

滿足以上要求的對(duì)象,就是迭代器。

迭代隱含的操作

在每次的迭代語句中,python都會(huì)按照迭代協(xié)議去對(duì)迭代器進(jìn)行迭代。其實(shí),在實(shí)際執(zhí)行中,python會(huì)進(jìn)行一些其他的操作:

將需要迭代的對(duì)象作為參數(shù)傳遞給iter函數(shù)

iter返回一個(gè)迭代器對(duì)象

每次循環(huán)則將返回的迭代器對(duì)象傳遞給next函數(shù)

循環(huán)至最后一個(gè)元素,觸發(fā)StopIteration

for語句為例
當(dāng)我們?cè)赑ython中執(zhí)行循環(huán)語句for i in foo的時(shí)候,其背后的操作是:

foo = iter(foo)

next(foo)

next(foo)在python3中執(zhí)行的是:foo.__next__(),在python2中則是:foo.next()

迭代器的實(shí)現(xiàn)

迭代器是用class來實(shí)現(xiàn)的。其中必需實(shí)現(xiàn)的有兩個(gè)方法:__iter__next(python2)/__next__(python3)。其中,__iter__必需返回一個(gè)迭代器對(duì)象,next則負(fù)責(zé)迭代邏輯并在迭代完畢時(shí)觸發(fā)異常。

如下:

def Iter(object)
    def __init__(self):
        pass
    def __iter__(self):
        pass
    def __next__(self):    # python3
        pass
    def next(self):        # python2
        pass

迭代器的特殊情況 迭代器的__iter__返回self

迭代器的__iter__方法需要返回的是一個(gè)具有next方法的可迭代對(duì)象。如果當(dāng)__iter__返回的是self的話,就會(huì)產(chǎn)生其他意想不到的效果。

class yrange:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return self

    def next(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()
            
class zrange:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return zrange(self.n)
        
    def next(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

執(zhí)行結(jié)果:

>>> y = yrange(5)
>>> list(y)
[0, 1, 2, 3, 4]
>>> list(y)
[]
>>> z = zrange(5)
>>> list(z)
[0, 1, 2, 3, 4]
>>> list(z)
[0, 1, 2, 3, 4]

yrange中,iter返回的是self,在執(zhí)行list(y)時(shí)iter返回的都是同一個(gè)self,所以再次調(diào)用list(y)時(shí)只會(huì)觸發(fā)結(jié)束迭代異常,列表中并無內(nèi)容。
而在zrange中,每次執(zhí)行list(z)時(shí),iter都是返回一個(gè)新的迭代器zrange(self.n),所以每次執(zhí)行list(z)都得到完整的元素。

生成器的迭代

通常,對(duì)于數(shù)據(jù)量特別大的序列,我們會(huì)用生成器generator來代替容器對(duì)象container,這樣可以利用lazy evaluable來節(jié)省內(nèi)存開銷。值得注意的是,生成器也是一個(gè)只能迭代一次的迭代器。

def grange(n):
    i = 0
    while i < n:
        yield i
        i += 1

執(zhí)行結(jié)果:

>>> glist = grange(10)
>>> list(glist)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(glist)
[]

如果是利用便捷的生成器表達(dá)式也是一樣:

>>> alist = (i for i in range(10))
>>> list(alist)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(alist)
[]

要解決這個(gè)問題,可以將迭代器和生成器組合使用:

class Grange(object):
    def __init__(self, n):
        self.n = n
    
    def __iter__(self):
        for i in range(self.n):
            yield i

結(jié)果:

>>> glist = Grange(10)
>>> list(glist)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(glist)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

值得注意的是,平常我們利用到生成器的地方都是數(shù)據(jù)量特別大的情況,這個(gè)時(shí)候,其實(shí)應(yīng)該盡量避免多次迭代生成器。我想這應(yīng)該也是python沒有支持對(duì)生成器多次迭代的特性的原因。

編程建議

在實(shí)際的編程中,往往需要在函數(shù)中多次迭代一個(gè)序列,如果這個(gè)序列是調(diào)用API得到的,而你又不能保證它是沒有陷阱的迭代器時(shí)??梢栽诒闅v迭代器的時(shí)候,加入一個(gè)判斷語句,避免無法多次迭代的情況發(fā)生:

def iterator_checker(iterator):
    assert iter(iterator) is not iter(iterator), "iter() return self"
參考資料

python官網(wǎng)迭代器文檔

python practice book

<>

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/38062.html

相關(guān)文章

  • Python學(xué)習(xí)--最完整的基礎(chǔ)知識(shí)大全

    摘要:迭代器對(duì)象從集合的第一個(gè)元素開始訪問,直到所有的元素被訪問完結(jié)束。迭代器有兩個(gè)基本的方法和。調(diào)用一個(gè)生成器函數(shù),返回的是一個(gè)迭代器對(duì)象。生成器函數(shù)生成器函數(shù)返回一個(gè)迭代器函數(shù)函數(shù)傳入不定長參數(shù)加了星號(hào)的變量名會(huì)存放所有未命名的變量參數(shù)。 Python學(xué)習(xí)--最完整的基礎(chǔ)知識(shí)大全 關(guān)于python的基礎(chǔ)知識(shí)學(xué)習(xí),網(wǎng)上有很多資料,今天我就把我收藏的整理一下分享給大家! 菜鳥教程pytho...

    王笑朝 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式·迭代模式

    摘要:迭代器模式原文地址更多設(shè)計(jì)模式系列教程更多免費(fèi)教程博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。迭代器模式常見和常用的有內(nèi)部迭代器外部迭代器倒序迭代器等等。 迭代器模式·原文地址 更多《設(shè)計(jì)模式系列教程》 更多免費(fèi)教程 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(靠這吃飯)和python(純粹喜歡...

    沈儉 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式·迭代模式

    摘要:迭代器模式原文地址更多設(shè)計(jì)模式系列教程更多免費(fèi)教程博主按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用靠這吃飯和純粹喜歡兩種語言實(shí)現(xiàn)。迭代器模式常見和常用的有內(nèi)部迭代器外部迭代器倒序迭代器等等。 迭代器模式·原文地址 更多《設(shè)計(jì)模式系列教程》 更多免費(fèi)教程 博主按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript(靠這吃飯)和python(純粹喜歡...

    newsning 評(píng)論0 收藏0
  • 首次公開,整理12年積累的博客收藏夾,零距離展示《收藏夾吃灰》系列博客

    摘要:時(shí)間永遠(yuǎn)都過得那么快,一晃從年注冊(cè),到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時(shí)候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...

    Harriet666 評(píng)論0 收藏0
  • 干貨 | 學(xué)習(xí)Python的正確姿勢(shì)

    摘要:勤學(xué)學(xué)習(xí)效率與效果取決于執(zhí)行力。這一步學(xué)習(xí)的正確姿勢(shì)是在實(shí)踐操作中發(fā)掘問題,然后帶著問題找答案。拆分任務(wù)將目標(biāo)分解成具體可執(zhí)行的學(xué)習(xí)任務(wù)。勤學(xué)強(qiáng)大的執(zhí)行力是學(xué)習(xí)的根本保障。分享復(fù)述檢驗(yàn)學(xué)習(xí)成果,提高學(xué)習(xí)效果的最好方法。 showImg(https://segmentfault.com/img/bVbcPGZ?w=256&h=256); 前段時(shí)間和大家一起分享了一篇關(guān)于學(xué)習(xí)方法內(nèi)容《大牛...

    Thanatos 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<