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

資訊專欄INFORMATION COLUMN

python奇遇記:迭代器和生成器

atinosun / 502人閱讀

摘要:來說說迭代器和生成器,還有可迭代對(duì)象和生成器表達(dá)式。有點(diǎn)繞是不是,其實(shí),一般只要知道可迭代對(duì)象以及它是如何實(shí)現(xiàn)的就行了,中常常用生成器來代替迭代器,可以說,生成器就是迭代器。

來說說迭代器和生成器,還有可迭代對(duì)象和生成器表達(dá)式。

之前簡單的提到過,一個(gè)對(duì)象是可迭代的可以理解為能夠使用for循環(huán)。這樣說其實(shí)不太準(zhǔn)確,某個(gè)對(duì)象可迭代是因?yàn)樗鼉?nèi)部實(shí)現(xiàn)了$__iter__$這個(gè)特殊方法。比如在python中,序列類型(列表,元組這些)都是可以迭代的,因?yàn)閮?nèi)部都有$__iter__$方法的實(shí)現(xiàn)。

不過,其實(shí)我們不用特別的實(shí)現(xiàn)$__iter__$方法,只要實(shí)現(xiàn)了$__getitem__$方法就可以。這個(gè)方法我之前介紹過,實(shí)現(xiàn)它之后就可以進(jìn)行切片以及迭代操作。為什么?因?yàn)樵趯?duì)一個(gè)對(duì)象迭代時(shí)如果找不到$__iter__$方法,python會(huì)自動(dòng)去尋找$__getitem__$方法,然后構(gòu)造一個(gè)迭代器,從0開始獲取元素。

說了半天,迭代器又是什么東西?可迭代對(duì)象,迭代器,這兩個(gè)是一樣的嗎?

迭代器是實(shí)現(xiàn)了$__next__$特殊方法的對(duì)象,而可迭代對(duì)象實(shí)現(xiàn)了$__iter__$方法,如果你需要迭代器能夠迭代自身,也需要實(shí)現(xiàn)$__iter__$方法。要注意的是,可迭代的對(duì)象必須實(shí)現(xiàn)$__iter__$方法,但不能實(shí)現(xiàn) $__next__$ 方法。

在迭代器中實(shí)現(xiàn)了$__next__$方法,你就能使用next(data)來依次產(chǎn)出數(shù)據(jù),如果此時(shí)沒有數(shù)據(jù)了,就會(huì)產(chǎn)生異常。像生孩子一樣,next一下生一個(gè)。

有點(diǎn)繞是不是,其實(shí),一般只要知道可迭代對(duì)象以及它是如何實(shí)現(xiàn)的就行了,python 中常常用生成器來代替迭代器,可以說,生成器就是迭代器。因?yàn)樯善饕矊?shí)現(xiàn)了$__iter__$和$__next__$方法。

python中還有一個(gè)iter函數(shù)用來生成迭代器,比如把一個(gè)列表放進(jìn)去,就可以使用next方法來一個(gè)個(gè)調(diào)用了。

說了這么多,來看個(gè)例子。

data = [1, 2, 3, 4]

# data是列表,是個(gè)可迭代對(duì)象
# 使用循環(huán)迭代
for i, j in enumerate(data):
    print(i, j)

# 生成一個(gè)迭代器
d = iter(data)
# 調(diào)用next
next(d)
# 調(diào)用四次之后就會(huì)產(chǎn)生異常
0 1
1 2
2 3
3 4





1


我們來自己實(shí)現(xiàn)一個(gè)迭代器。

# 從后往前產(chǎn)出列表中的數(shù)據(jù)
class ReverseList:

    def __init__(self, item):
       #用range構(gòu)造一個(gè)列表
        self.list = list(range(item))

    def __iter__(self):
        return self

    def __next__(self):

        try:
            return self.list.pop()
        except:
            raise StopIteration

用一下試試。

data = ReverseList(4)

# 調(diào)用next,從后往前產(chǎn)出數(shù)據(jù)
print(next(data))
print(next(data))
print(next(data))
print(next(data))
# 如果繼續(xù)調(diào)用,會(huì)產(chǎn)生錯(cuò)誤,因?yàn)闆]有數(shù)據(jù)可產(chǎn)出了
print(next(data))
3
2
1
0



---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

 in __next__(self)
     12         try:
---> 13             return self.list.pop()
     14         except:


IndexError: pop from empty list


During handling of the above exception, another exception occurred:


StopIteration                             Traceback (most recent call last)

 in ()
      7 print(next(data))
      8 # 如果繼續(xù)調(diào)用,會(huì)產(chǎn)生錯(cuò)誤,因?yàn)闆]有數(shù)據(jù)可產(chǎn)出了
----> 9 print(next(data))


 in __next__(self)
     13             return self.list.pop()
     14         except:
---> 15             raise StopIteration


StopIteration: 

那什么又是生成器?

在程序設(shè)計(jì)中,內(nèi)存是個(gè)很寶貴的東西,占用太多的內(nèi)存總是不好的,生成器的作用就是我先把你的數(shù)據(jù)表示出來,但是實(shí)際上并不占用內(nèi)存空間,只有在你調(diào)用它時(shí)才會(huì)占用。一般情況下,比如你定義了一個(gè)列表,會(huì)自動(dòng)的使用一段內(nèi)存空間。

在 python中,只要定義了yield關(guān)鍵字的函數(shù)就是生成器。上面說了,生成器就是迭代器,你可以進(jìn)行迭代操作(循環(huán)),調(diào)用next來一個(gè)個(gè)產(chǎn)出數(shù)據(jù)。

def gen123():
    yield 1
    yield 2
    yield 3

for i in gen123():
    print(i)

g = gen123()
print(next(g))
1
2
3
1

雖然說生成器就是迭代器,但是在python的定義中,迭代器用來遍歷集合,從中產(chǎn)出元素,而生成器無需遍歷集合就能生成值,比如range()函數(shù),生成器不僅能夠產(chǎn)出集合中的元素,還可以產(chǎn)出派生自元素的其他值。

我在上一篇文章(Python奇遇記:數(shù)據(jù)結(jié)構(gòu)窺探2)中提到過生成器表達(dá)式,只介紹了一下它的用法,那么生成器表達(dá)式是什么東西?

其實(shí),生成器表達(dá)式就是生成器的快速實(shí)現(xiàn)而已,類似于之前講過的具名元組。有些時(shí)候需要快速的生成一段數(shù)據(jù),使用生成器表達(dá)式即可,無需定義函數(shù)再調(diào)用。


本人才疏學(xué)淺,上文中難免有些錯(cuò)誤,還請(qǐng)各位品評(píng)指正。如果覺得寫的還行,歡迎關(guān)注我的公眾號(hào)MLGroup,帶你走進(jìn)機(jī)器學(xué)習(xí)的世界。

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

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

相關(guān)文章

  • Python奇遇:數(shù)據(jù)結(jié)構(gòu)窺探

    摘要:擠掉了堆中實(shí)現(xiàn)了堆排序。你可以用堆排序來查找一個(gè)序列中最大的或者最小的幾個(gè)元素。除了使用堆排序,中還有排序和,這兩個(gè)排序最終生成以列表表示的排序結(jié)果,堆排序也是。 這次我們來說說python中的數(shù)據(jù)結(jié)構(gòu)。當(dāng)然了,不會(huì)講很基礎(chǔ)的內(nèi)容。 用過python的都知道,python有著與其他語言很不一樣的數(shù)據(jù)類型,像什么列表、元組、集合、字典之類。這些數(shù)據(jù)類型造就了python簡單易用同時(shí)又很強(qiáng)...

    mrli2016 評(píng)論0 收藏0
  • Python奇遇:數(shù)據(jù)結(jié)構(gòu)窺探2

    摘要:找出列表中小于的數(shù)據(jù)除了列表推導(dǎo)式,還有字典推導(dǎo)式,集合推導(dǎo)式,用法都一樣。如果你的數(shù)據(jù)量很大的話,考慮使用生成器表達(dá)式。切片不僅對(duì)列表有用,同樣適用于元組和字符串。切片命名使用方法,內(nèi)部參數(shù)與切片一樣。對(duì)剩余的的數(shù)據(jù),使用星號(hào)代替即可。 上次我們講了幾個(gè)不常見的數(shù)據(jù)類型,每個(gè)都有自己特殊的用途,雖然不經(jīng)常用到,了解一下也好。比如我們提到的數(shù)組類型,如果在數(shù)據(jù)量很大的時(shí)候同時(shí)要效率,就...

    Ocean 評(píng)論0 收藏0
  • Python奇遇:特殊方法窺探

    摘要:在中,特殊方法以雙下劃線開始,以雙下劃線結(jié)束。真假值,如果向量模為,返回實(shí)現(xiàn)向量加法實(shí)現(xiàn)向量乘法,例如返回向量的模返回歐幾里德范數(shù)找個(gè)例子運(yùn)行下。怎么辦中有個(gè)特殊方法,可以修改控制臺(tái)輸出的樣式。 什么是特殊方法?當(dāng)我們?cè)谠O(shè)計(jì)一個(gè)類的時(shí)候,python中有一個(gè)用于初始化的方法$__init__$,類似于java中的構(gòu)造器,這個(gè)就是特殊方法,也叫作魔術(shù)方法。簡單來說,特殊方法可以給你設(shè)計(jì)的...

    niceforbear 評(píng)論0 收藏0
  • python協(xié)程的前世今生

    摘要:協(xié)程的歷史說來話長,要從生成器開始講起。我們可以使用把數(shù)據(jù)發(fā)送給協(xié)程函數(shù)??梢钥吹剑诘诖谓邮胀陻?shù)據(jù)之后,會(huì)產(chǎn)生結(jié)束的異常,因?yàn)槌绦蛄鞒探Y(jié)束了,這是正?,F(xiàn)象。在這個(gè)階段,協(xié)程本質(zhì)上還是由生成器構(gòu)成的。所以,協(xié)程的介紹到這里就結(jié)束啦。 在上一篇對(duì)python并發(fā)編程的理解 中,我簡單提到了協(xié)程的概念,有一個(gè)錯(cuò)誤需要指出的是,asyncio不全是對(duì)協(xié)程的實(shí)現(xiàn),只是用到了協(xié)程。 協(xié)程的歷史說...

    stackfing 評(píng)論0 收藏0
  • python奇遇:數(shù)據(jù)結(jié)構(gòu)窺探3

    摘要:字典和集合都是基于散列表實(shí)現(xiàn)的,散列表也就是表,了解過數(shù)據(jù)結(jié)構(gòu)的應(yīng)該知道。而使用另一種辦法,任何鍵在找不到的情況下都會(huì)用中的值數(shù)據(jù)類型比如替換。在設(shè)計(jì)時(shí)就可以使用創(chuàng)建你的數(shù)據(jù)接口。 這次主要說說字典和集合這兩種數(shù)據(jù)類型。 字典和集合都是基于散列表實(shí)現(xiàn)的,散列表也就是hash表,了解過數(shù)據(jù)結(jié)構(gòu)的應(yīng)該知道。與散列表相關(guān)的一個(gè)概念叫做可散列,什么是可散列?在python官方定義中是這樣說的:...

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

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

0條評(píng)論

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