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

一文搞懂python 中的迭代器和生成器

 更新時(shí)間:2022年03月06日 14:59:17   作者:海天之涯  
這篇文章主要介紹了python 中的迭代器和生成器簡(jiǎn)單介紹,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

可迭代對(duì)象和迭代器

迭代(iterate)意味著重復(fù),就像 for 循環(huán)迭代序列和字典那樣,但實(shí)際上也可使用 for 循環(huán)迭代其他對(duì)象:實(shí)現(xiàn)了方法 __iter__ 的對(duì)象(迭代器協(xié)議的基礎(chǔ))。
__iter__方法返回一個(gè)迭代器,它是包含方法 __next__ 的對(duì)象,調(diào)用時(shí)可不提供任何參數(shù);
當(dāng)你調(diào)用 __next__ 時(shí),迭代器應(yīng)返回其下一個(gè)值;如果沒(méi)有可供返回的值,應(yīng)引發(fā) StopIteration 異常;
也可使用內(nèi)置函數(shù) next(),此種情況下,next(it) 與 it.__next()__ 等效。

至于為什么不用列表?因?yàn)樵诤芏嗲闆r下,使用列表都有點(diǎn)太浪費(fèi)了。例如,如果你有一個(gè)可逐個(gè)計(jì)算值的函數(shù),你可能只想逐個(gè)地獲取值,而不是使用列表一次性獲取。這是因?yàn)槿绻泻芏嘀?,列表可能占用太多的?nèi)存。
下面來(lái)看一個(gè)不能使用列表的示例,因?yàn)槿绻褂茫@個(gè)列表的長(zhǎng)度將是無(wú)窮大的!

# 這個(gè)“列表”為斐波那契數(shù)列,表示該數(shù)列的迭代器如下:
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        return self.a  # 前面邏輯自定義,最后返回下一個(gè)值即可
    def __iter__(self):
        return self  # 返回迭代器本身(一個(gè)包含 __next__ 方法的對(duì)象)
    
fibs = Fibs()
for f in fibs:
	if f > 1000:
		print(f)  # 1597
		break  # 若不中斷循環(huán),將一直循環(huán)下去
        
next(fibs)  # 2584
next(fibs)  # 4181

更正規(guī)的定義是,實(shí)現(xiàn)了方法 __iter__ 的對(duì)象是 可迭代的,再實(shí)現(xiàn)了方法 __next__ 的對(duì)象是 迭代器。

內(nèi)置函數(shù) iter()

通過(guò)對(duì)可迭代對(duì)象調(diào)用內(nèi)置函數(shù) iter(),可以獲得一個(gè)迭代器。還可使用它從函數(shù)或其他可調(diào)用對(duì)象創(chuàng)建可迭代對(duì)象。
不過(guò),可迭代對(duì)象在轉(zhuǎn)化為迭代器后,會(huì)丟失?些屬性(如 __getitem__() ),但同時(shí)也會(huì)增加?些屬性(如 __next__() )。
另外,迭代器一般都是?次性的,當(dāng)?shù)^(guò)?輪后,再次迭代將獲取不到元素;而可迭代對(duì)象可以重復(fù)使用。

it = iter([1, 2, 3])  # list 是可迭代對(duì)象哦
next(it)  # 1
next(it)  # 2
next(it)  # 3
next(it)  # StopIretation; 普通的可迭代對(duì)象是可復(fù)用的,而迭代器是一次性的,回不了頭的

it = iter("ABCD")  # string 也是可迭代對(duì)象
for i in it:
    print(i, end=" ")  # A B C D
for i in it:
    print(i, end=" ")  # ?輸出

查看對(duì)象是否實(shí)現(xiàn)了魔法方法 _iter_ 的四種方法:

# ?法1:dir()查看__iter__,詳情請(qǐng)自己嘗試
dir(2) # 沒(méi)有
dir("abc") # 有 __iter__()
# ?法2:isinstance()判斷
import collections
isinstance(2, collections.Iterable) # False
isinstance("abc", collections.Iterable) # True
# ?法3:hasattr()判斷
hasattr(2,"__iter__") # False
hasattr("abc","__iter__") # True
# ?法4:?iter()查看是否報(bào)錯(cuò)
iter(2) # 報(bào)錯(cuò):'int' object is not iterable
iter("abc") # <str_iterator at 0x1e2396d8f28>

從迭代器創(chuàng)建序列

在可以使用序列的情況下,大多也可以使用迭代器或可迭代對(duì)象(諸如索引和切片等操作除外)。迭代器因?yàn)槿鄙?__getitem__ ,因此不能使?普通的切?語(yǔ)法,暫未深究。

# 使用構(gòu)造函數(shù) list() 顯示的將迭代器轉(zhuǎn)換為列表
class TestIterator:
    value = 0
    
    def __next__(self):
        self.value += 1
        if self.value > 10: raise StopIteration
        return self.value
    def __iter__(self):
        return self
ti = TestIterator()
ti2 = list(ti)  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i in ti2:
    print(i, end=" ")  # 1 2 3 4 5 6 7 8 9 10
        
print('the second:')

生成器

生成器,也被稱(chēng)為簡(jiǎn)單生成器(simple generator),生成器自動(dòng)創(chuàng)建了 iter() 和 next() 方法,是一種使用普通函數(shù)語(yǔ)法定義的迭代器。與函數(shù)的主要的形式差別就在于,它的函數(shù)體中有一句 yield 語(yǔ)句。
每次執(zhí)行到 yield 處時(shí),生成并返回一個(gè)值后,函數(shù)都將暫時(shí)停止執(zhí)行,等待下一輪迭代調(diào)用,如此往復(fù),直到迭代完。數(shù)據(jù)量大時(shí),生成器能夠極大地節(jié)省內(nèi)存空間。下面還是通過(guò)斐波納契數(shù)列來(lái)看看:

# 斐波納契數(shù)列的生成器實(shí)現(xiàn): 返回?cái)?shù)列的前 n 項(xiàng)
def fibs(n):
    a, b = 0, 1
    for _ in range(n):
        yield a  # 返回的是一個(gè)生成器
        a, b = b, b+a
f = fibs(5)
print(f)  # <generator object fibs at 0x05BB20B0>
print(list(f))  # [0, 1, 1, 2, 3]; 此處生成器 f 已經(jīng)被迭代過(guò)一次了
for i in f:
    print(i, end=" ")  # ?輸出; for循環(huán)會(huì)?動(dòng)捕捉到 StopIteration 異常并停?調(diào)? next()
    
print(next(f))  # StopIteration

與 return 的區(qū)別:生成器不是像 return 一樣返回一個(gè)值,而是可以生成多個(gè)值,每次返回一個(gè);return 返回的話(huà),這個(gè)函數(shù)就結(jié)束了。

生成器推導(dǎo)(生成式表達(dá)式)

將列表生成式的 [] 改成 () 之后,數(shù)據(jù)結(jié)構(gòu)將從列表變?yōu)樯善?,而不是元組。如果要包裝可迭代對(duì)象(可能生成大量的值)時(shí),若使用列表推導(dǎo)將立即實(shí)例化一個(gè)列表,從而喪失迭代的優(yōu)勢(shì);但如果使用生成器推導(dǎo)的話(huà),每迭代一次就生成一個(gè)值,沒(méi)必要一次性生成全部值,這樣就好的多了。而且,可以直接在既有的圓括號(hào)內(nèi)(如在函數(shù)調(diào)用中)使用生成器推導(dǎo)時(shí),無(wú)需再添加一對(duì)圓括號(hào)。

L = [x*x for x in range(10)]  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g = (x*x for x in range(10))  # <generator object <genexpr> at 0x052AF8F0>
print(next(g))  # 0
sum(i ** 2 for i in range(10))  # 285

遞歸式生成器

創(chuàng)建一個(gè)將兩層嵌套列表展開(kāi)的函數(shù):

nested = [[1, 2], [3, 4], [5], 6]
def flatten(nested):
    try:
        for sub in nested:
            for ele in sub:
                yield ele
    except TypeError:
        yield sub
            
f = flatten(nested)
next(f)  # 1
# print(list(f))  # [2, 3, 4, 5, 6]
for i in f3:
    print(i)  # 2 3 4 5 6

創(chuàng)建一個(gè)將任意層嵌套列表展開(kāi)的函數(shù):
對(duì)一層列表進(jìn)行遍歷,遍歷下層列表的時(shí)候,先對(duì)一層遍歷出來(lái)的元素再調(diào)用一次 flatten 函數(shù),這時(shí),如果是不可再迭代的對(duì)象的話(huà),就會(huì)報(bào) TypeError 錯(cuò)誤,捕捉到之后,yeild 返回,繼續(xù)下一個(gè);如果是可迭代的話(huà),就遞歸下去;

def flatten(nested):
    try:
        for sub in nested:
            for ele in flatten(sub):
                yield ele
    except TypeError:
        yield nested
        
nested = [[[1], 2], 3, 4, [5, [6, 7]], 8]
print(list(flatten(nested)))

不過(guò),上面要注意的是:前面也提到了,字符串對(duì)象也是可迭代的,而且一般我們也不會(huì)將它拆開(kāi)。更重要的是,字符串的第一個(gè)元素是一個(gè)長(zhǎng)度為 1 的字符串,而長(zhǎng)度為 1 的字符串的第一個(gè)元素是字符串本身。

s = 'ABCD'
s2 = s[0]  # 'A'
s2[0]  # 'A'

這樣子會(huì)造成無(wú)窮遞歸的。所以還需要檢查一下對(duì)象是否類(lèi)似于字符串:

def flatten(nested):    
    try:
        if isinstance(nested, str): raise TypeError
            
        for sub in nested:
            for ele in flatten(sub):
                yield ele
    except TypeError:
        yield nested
        
nested = [[[1], '23'], 3, '43', [5, [6, '73']], 8]
print(list(flatten(nested)))  # [1, '23', 3, '43', 5, 6, '73', 8]

不過(guò),它有兩個(gè) yield 唉,這認(rèn)哪個(gè)來(lái)著???pass

def flatten(nested):
	try:
		for sublist in nested:
			for element in flatten(sublist):
				print("element:", element)
				yield element
	except TypeError:
		print("nested :", nested)
		yield nested
		
print(list(flatten([[1, 2], [3, 4], [5], 6])))

輸出:

nested : 1
element: 1   
nested : 2
element: 2
nested : 3
element: 3
nested : 4
element: 4
nested : 5
element: 5
nested : 6
element: 6
[1, 2, 3, 4, 5, 6]

到此這篇關(guān)于python 中的迭代器和生成器簡(jiǎn)單介紹的文章就介紹到這了,更多相關(guān)python 迭代器和生成器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python3.6實(shí)現(xiàn)連接mysql或mariadb的方法分析

    Python3.6實(shí)現(xiàn)連接mysql或mariadb的方法分析

    這篇文章主要介紹了Python3.6實(shí)現(xiàn)連接mysql或mariadb的方法,結(jié)合實(shí)例形式分析了Python3.6針對(duì)mysql或mariadb數(shù)據(jù)庫(kù)操作的相關(guān)模塊安裝、數(shù)據(jù)庫(kù)與表的創(chuàng)建、數(shù)據(jù)庫(kù)連接等操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-05-05
  • python opencv 圖像邊框(填充)添加及圖像混合的實(shí)現(xiàn)方法(末尾實(shí)現(xiàn)類(lèi)似幻燈片漸變的效果)

    python opencv 圖像邊框(填充)添加及圖像混合的實(shí)現(xiàn)方法(末尾實(shí)現(xiàn)類(lèi)似幻燈片漸變的效果)

    這篇文章主要介紹了python opencv 圖像邊框(填充)添加及圖像混合(末尾實(shí)現(xiàn)類(lèi)似幻燈片漸變的效果),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • ubuntu 安裝pyqt5和卸載pyQt5的方法

    ubuntu 安裝pyqt5和卸載pyQt5的方法

    這篇文章主要介紹了ubuntu 安裝pyqt5和卸載pyQt5的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • python數(shù)據(jù)分析必會(huì)的Pandas技巧匯總

    python數(shù)據(jù)分析必會(huì)的Pandas技巧匯總

    用Python做數(shù)據(jù)分析光是掌握numpy和matplotlib可不夠,numpy雖然能夠幫我們處理處理數(shù)值型數(shù)據(jù),但很多時(shí)候,還有字符串,還有時(shí)間序列等,比如:我們通過(guò)爬蟲(chóng)獲取到了存儲(chǔ)在數(shù)據(jù)庫(kù)中的數(shù)據(jù),一些Pandas必會(huì)的用法,讓你的數(shù)據(jù)分析水平更上一層樓
    2021-08-08
  • 深度解析Python中的情感分析與情緒識(shí)別

    深度解析Python中的情感分析與情緒識(shí)別

    在當(dāng)今數(shù)字化時(shí)代,情感分析與情緒識(shí)別技術(shù)日益成為人機(jī)交互,社交媒體分析,智能客服等領(lǐng)域的重要應(yīng)用,下面我們就來(lái)深入聊聊基于Python的情感分析與情緒識(shí)別技術(shù)吧
    2025-03-03
  • 如何使用?profile?進(jìn)行python代碼性能分析

    如何使用?profile?進(jìn)行python代碼性能分析

    對(duì)代碼優(yōu)化的前提是需要了解性能瓶頸在什么地方,程序運(yùn)行的主要時(shí)間是消耗在哪里,對(duì)于比較復(fù)雜的代碼可以借助一些工具來(lái)定位,python?內(nèi)置了豐富的性能分析工具,本文介紹如何使用profile進(jìn)行python代碼性能分析,感興趣的朋友一起看看吧
    2024-12-12
  • python讀取大文件越來(lái)越慢的原因與解決

    python讀取大文件越來(lái)越慢的原因與解決

    這篇文章主要給大家介紹了關(guān)于python讀取大文件越來(lái)越慢的原因與解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python通過(guò)正則庫(kù)爬取淘寶商品信息代碼實(shí)例

    Python通過(guò)正則庫(kù)爬取淘寶商品信息代碼實(shí)例

    這篇文章主要介紹了Python通過(guò)正則庫(kù)爬取淘寶商品信息代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Python實(shí)現(xiàn)程序的單一實(shí)例用法分析

    Python實(shí)現(xiàn)程序的單一實(shí)例用法分析

    這篇文章主要介紹了Python實(shí)現(xiàn)程序的單一實(shí)例用法,較為詳細(xì)的分析了Python窗口的相關(guān)操作技巧,需要的朋友可以參考下
    2015-06-06
  • 解決Python找不到ssl模塊問(wèn)題 No module named _ssl的方法

    解決Python找不到ssl模塊問(wèn)題 No module named _ssl的方法

    這篇文章主要介紹了解決Python找不到ssl模塊問(wèn)題 No module named _ssl的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04

最新評(píng)論

中超| 策勒县| 棋牌| 高清| 桐庐县| 社旗县| 白玉县| 西宁市| 汉中市| 麻城市| 东乡县| 牡丹江市| 商水县| 溧阳市| 长治市| 广南县| 灌南县| 兴和县| 吴旗县| 九龙坡区| 荔波县| 唐河县| 化州市| 凤山市| 兰溪市| 图木舒克市| 临邑县| 清远市| 桂阳县| 略阳县| 临汾市| 吉安市| 乌苏市| 乐平市| 潞西市| 江华| 北宁市| 清远市| 驻马店市| 湄潭县| 收藏|