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

Python中的迭代器與生成器使用及說明

 更新時間:2022年12月16日 12:24:08   作者:Lareges  
這篇文章主要介紹了Python中的迭代器與生成器使用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

一、迭代器(Iterator)

1.1 可迭代對象(Iterable)

可迭代對象,可以簡單理解為可遍歷對象,即能夠使用 for 循環(huán)遍歷的對象。Python中常見的可迭代對象有:列表、元組、字符串、集合、range、字典等。

迭代器和生成器都是可迭代對象。

對于Python中的任意對象,只要它定義了可以返回一個迭代器的 __iter__ 方法,或者定義了可以支持下標索引的 __getitem__ 方法,那么它就是一個可迭代對象。

對可迭代對象使用 __iter__ 方法后,會返回一個迭代器。

如何判斷一個對象是否為可迭代對象呢?請看下例。

from collections.abc import Iterable

isinstance([1, 2, 3], Iterable) ?# True
isinstance((1, 2, 3), Iterable) ?# True
isinstance('123', Iterable) ?# True
isinstance({1, 2, 3}, Iterable) ?# True
isinstance(range(3), Iterable) ?# True
isinstance({'key': 'value'}, Iterable) ?# True
isinstance(123, Iterable) ?# False

可以看出,我們只需要使用 isinstance(object, Iterable) 即可判斷給定的 object 是否為可迭代對象。

嚴格來講,isinstance() 只會將有 __iter__ 方法的對象判斷為 Iterable。

換言之,僅用 __getitem__ 方法實現(xiàn)的可迭代對象會被 isinstance() 誤判為不可迭代對象。

最正確的做法是直接嘗試 iter(object),如果沒有報錯,則說明 object 是可迭代對象。

1.2 將可迭代對象轉(zhuǎn)化為迭代器

我們可以將現(xiàn)有的可迭代對象轉(zhuǎn)化為可迭代器:

s = '12345'
myiter = iter(s)
myiter
# <str_iterator at 0x25e6f40d130>

不斷調(diào)用 next 方法來依次獲取迭代器的元素:

next(myiter)
# '1'
next(myiter)
# '2'
next(myiter)
# '3'
next(myiter)
# '4'
next(myiter)
# '5'
next(myiter)
# StopIteration:?

可見迭代器執(zhí)行到最后時會拋出一個 StopIteration 異常。

為避免這種異常,我們完全可以用更簡單的 for 循環(huán)去遍歷:

for e in myiter:
? ? print(e)
# 1
# 2
# 3
# 4
# 5

1.3 構(gòu)造迭代器

構(gòu)造一個迭代器只需要在自定義的類中實現(xiàn)兩個方法:__iter__ 和 __next__ 。

  • 迭代器是一個可以記住遍歷位置的對象。
  • 迭代器對象會從第一個元素開始訪問,直到所有元素都被訪問為止,且只能前進不能后退。

當我們構(gòu)造類時,必須要有一個名為 __init__() 的函數(shù),該函數(shù)可以在實例化時進行一些初始化。

  • __iter__() 方法的行為類似,可以執(zhí)行操作(初始化等),但必須始終返回迭代器對象本身。
  • __next__() 方法還允許你進行其他操作,并且必須返回序列中的下一項。
class MyIter:
? ? def __iter__(self):
? ? ? ? self.count = 1
? ? ? ? return self
? ??
? ? def __next__(self):
? ? ? ? x = self.count
? ? ? ? self.count += 1
? ? ? ? return x

我們創(chuàng)建了一個返回數(shù)字的迭代器,每次序列的數(shù)值都將 +1。

myiter = iter(MyIter())
next(myiter)
# 1
next(myiter)
# 2
next(myiter)
# 3

如果我們一直調(diào)用 next() 的方法,則序列的值將會無限遞增下去。即如果我們使用 for 循環(huán)去遍歷上述迭代器,循環(huán)將永遠進行下去…

myiter = iter(MyIter())
for e in myiter:
? ? print(e)
# 循環(huán)將一直進行下去...

為了防止迭代永遠進行下去,我們可以在迭代次數(shù)達到一定值時拋出 StopIteration 異常。

class MyIter:
? ? def __iter__(self):
? ? ? ? self.count = 1
? ? ? ? return self
? ??
? ? def __next__(self):
? ? ? ? if self.count <= 5:
? ? ? ? ? ? x = self.count
? ? ? ? ? ? self.count += 1
? ? ? ? ? ? return x
? ? ? ? else:
? ? ? ? ? ? raise StopIteration

這樣再執(zhí)行 for 循環(huán)就不會一直進行下去了:

myiter = iter(MyIter())
for e in myiter:
? ? print(e)
# 1
# 2
# 3
# 4
# 5

二、生成器(Generator)

在Python中,一邊迭代(循環(huán))一邊計算的機制,稱為生成器。生成器能夠迭代的關(guān)鍵是因為它有一個 __next__ 方法。

為什么要有生成器呢?我們知道,列表中的所有數(shù)據(jù)都存儲在內(nèi)存中,如果有海量數(shù)據(jù)的話將會非常消耗內(nèi)存。很多時候,我們只需要訪問列表中前面的元素,這樣一來后面的元素所占用的空間就白白浪費了。

如果列表元素能夠按照某種算法推算出來,那我們就可以在循環(huán)的過程中不斷推算出后續(xù)的元素,這樣就不必創(chuàng)建完整的列表,從而節(jié)省了大量的空間(即用多少就生成多少)。

有以下兩種常用方法來創(chuàng)建生成器:

將列表解析式中的 [] 改為 ()。在自定義的函數(shù)中使用 yield 關(guān)鍵字。此時這個函數(shù)就不再是一個普通函數(shù),而是一個生成器,調(diào)用該函數(shù)就是創(chuàng)建了一個生成器對象。

2.1 使用 () 構(gòu)造生成器

比較以下兩段代碼:

a = [x for x in range(3)]
type(a)
# list

a = (x for x in range(3))
type(a)
# generator

我們還可以比較列表解析式和生成器的耗時:

tic = time.time()
a = sum([x for x in range(10000000)])
toc = time.time()
print(toc - tic)
# 0.9081981182098389
tic = time.time()
a = sum((x for x in range(10000000)))
toc = time.time()
print(toc - tic)
# 0.6906485557556152

我們當然可以對生成器使用 next() 方法:

next(a)
# 0
next(a)
# 1
next(a)
# 2
next(a)
# StopIteration:?

但一般我們不會用 next() 來獲取下一個返回值,而是直接使用 for 循環(huán)來迭代。

2.2 使用帶有 yield 關(guān)鍵字的函數(shù)構(gòu)造生成器

帶有 yield 的函數(shù)不再是一個普通函數(shù),而是一個生成器。

yield 相當于return一個值,并且記住這個返回的位置,下次迭代時,代碼從 yield 的下一條語句開始執(zhí)行。

我們可以通過下面的例子先來理解一下:

def num():
? ? print('開始執(zhí)行')
? ? for i in range(5):
? ? ? ? yield i
? ? ? ? print('繼續(xù)執(zhí)行')


mygen = num()
type(mygen)
# generator

由此,我們成功創(chuàng)建了一個生成器對象。接下來調(diào)用 next 方法觀察這個生成器是如何工作的:

next(mygen)
# 開始執(zhí)行
# 0
next(mygen)
# 繼續(xù)執(zhí)行
# 1
next(mygen)
# 繼續(xù)執(zhí)行
# 2
next(mygen)
# 繼續(xù)執(zhí)行
# 3
next(mygen)
# 繼續(xù)執(zhí)行
# 4
next(mygen)
# StopIteration:

當然我們也可以使用 for 循環(huán)來遍歷這個生成器:

for step in mygen:
? ? print(step)
# 開始執(zhí)行
# 0
# 繼續(xù)執(zhí)行
# 1
# 繼續(xù)執(zhí)行
# 2
# 繼續(xù)執(zhí)行
# 3
# 繼續(xù)執(zhí)行
# 4
# 繼續(xù)執(zhí)行

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • pytorch 更改預(yù)訓(xùn)練模型網(wǎng)絡(luò)結(jié)構(gòu)的方法

    pytorch 更改預(yù)訓(xùn)練模型網(wǎng)絡(luò)結(jié)構(gòu)的方法

    今天小編就為大家分享一篇pytorch 更改預(yù)訓(xùn)練模型網(wǎng)絡(luò)結(jié)構(gòu)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • pytest實現(xiàn)多進程與多線程運行超好用的插件

    pytest實現(xiàn)多進程與多線程運行超好用的插件

    本文主要介紹了pytest實現(xiàn)多進程與多線程運行超好用的插件,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • .dcm格式文件軟件讀取及python處理詳解

    .dcm格式文件軟件讀取及python處理詳解

    今天小編就為大家分享一篇.dcm格式文件軟件讀取及python處理詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • python pandas中對Series數(shù)據(jù)進行軸向連接的實例

    python pandas中對Series數(shù)據(jù)進行軸向連接的實例

    今天小編就為大家分享一篇python pandas中對Series數(shù)據(jù)進行軸向連接的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • python爬蟲之scrapy框架詳解

    python爬蟲之scrapy框架詳解

    這篇文章主要為大家介紹了python爬蟲之scrapy框架,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • python中的日志文件按天分割

    python中的日志文件按天分割

    這篇文章主要介紹了python中的日志文件按天分割方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • python操作列表的函數(shù)使用代碼詳解

    python操作列表的函數(shù)使用代碼詳解

    這篇文章主要介紹了python操作列表的函數(shù)使用代碼詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Python實現(xiàn)SVN的目錄周期性備份實例

    Python實現(xiàn)SVN的目錄周期性備份實例

    這篇文章主要介紹了Python實現(xiàn)SVN的目錄周期性備份,實例分析了Python實現(xiàn)SVN周期性備份的原理與實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • python實現(xiàn)五子棋雙人對弈

    python實現(xiàn)五子棋雙人對弈

    這篇文章主要為大家詳細介紹了python實現(xiàn)五子棋雙人對弈,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Python閉包技巧介紹

    Python閉包技巧介紹

    這篇文章主要介紹了Python閉包,所謂閉包就是用函數(shù)代替類,被外層函數(shù)包圍的內(nèi)層函數(shù),它能夠獲取外層函數(shù)范圍中的變量,感興趣的小伙伴請和小編一起進入文章學(xué)習(xí)具體內(nèi)容吧
    2021-12-12

最新評論

上栗县| 大田县| 青阳县| 长岭县| 惠来县| 乌什县| 通榆县| 阿克| 张掖市| 临漳县| 昭苏县| 剑河县| 连州市| 南丰县| 宁化县| 军事| 新乐市| 嵩明县| 保康县| 定襄县| 革吉县| 宿松县| 中阳县| 水城县| 和龙市| 神池县| 万州区| 阿城市| 枣阳市| 丹凤县| 罗山县| 苗栗市| 东乡县| 巴青县| 灌南县| 商水县| 六枝特区| 阳西县| 宁夏| 龙泉市| 昌邑市|