免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

python迭代器和生成器-創(chuàng)新互聯(lián)

python中的迭代器

可迭代對(duì)象

迭代是指重復(fù)反饋過程,每一次的迭代都會(huì)得到一個(gè)結(jié)果,又是下一次迭代的開始。
在python中,一個(gè)對(duì)象只要是實(shí)現(xiàn)了__iter__() 或__getitem__()方法,就被稱為可迭代對(duì)象。

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比茅箭網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式茅箭網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋茅箭地區(qū)。費(fèi)用合理售后完善,十年實(shí)體公司更值得信賴。

python中的可迭代對(duì)象有字符串、列表、元組、字典、文件;自定義的類若是實(shí)現(xiàn)了__iter__() 或__getitem__()方法,則也是可迭代對(duì)象~

遍歷可迭代對(duì)象,這里僅以文件為例:

with open(file='/Users/luyi/tmp/abc', mode='r', encoding='utf-8') as f:
    for line in f:
        print(line, end='')

迭代器

調(diào)用可迭代對(duì)象的__iter__() 方法,返回得到的就是一個(gè)迭代器,迭代器用于迭代可迭代對(duì)象中的每一個(gè)元素。

迭代器有兩個(gè)方法:__iter__() 方法,__next__() 方法,調(diào)用迭代器的__iter__() 方法,返回的依舊是迭代器對(duì)象,即將自身返回。不斷的調(diào)用__next__() 方法,則會(huì)逐個(gè)返回可迭代對(duì)象中的元素~

with open(file='/Users/luyi/tmp/abc', mode='r', encoding='utf-8') as f:  # abc 文件中僅有3行內(nèi)容
    file_iter = f.__iter__()                      # 獲取迭代器對(duì)象     
    print(file_iter.__next__(), end='')    # 讀取第一行內(nèi)容
    print(file_iter.__next__(), end='')    # 讀取第二行內(nèi)容
    print(file_iter.__next__(), end='')    # 讀取第三行內(nèi)容
    print(file_iter.__next__(), end='')    # 對(duì)象中的元素已經(jīng)全部迭代完成,所以這一行會(huì)拋出 StopIteration 異常

輸出結(jié)果:
aaa
bbb
ccc
...                # 省略部分報(bào)錯(cuò)信息
StopIteration

如上所示,在獲取可迭代對(duì)象的迭代器之后,不斷調(diào)用迭代器的__next__() 方法,以遍歷其中的所有元素,當(dāng)全部遍歷完成后,再次調(diào)用__next__() 方法,就會(huì)拋出 StopIteration 異常

遍歷玩所有的元素,這樣寫會(huì)比較麻煩,因?yàn)樾枰粩嗟恼{(diào)用__next__() 方法,其實(shí)這里可以使用 for 循環(huán)替代,實(shí)現(xiàn)的方式在 實(shí)例1 中已經(jīng)給出。

for...in... 循環(huán)的過程

for item in Iterable 循環(huán) 會(huì)調(diào)用 in 后面對(duì)象的 __iter__() 方法,得到迭代器,然后自動(dòng)的,不斷的 調(diào)用迭代器的__next__()方法,得到的返回值 賦值給 for 前面的item 變量,這樣依次循環(huán);直到調(diào)用__next__()方法時(shí)報(bào)錯(cuò)(StopIteration異常),for循環(huán)會(huì)自動(dòng)捕獲異常,然后循環(huán)結(jié)束~

Iterable, Iterator

Iterable, Iterator 用于判斷一個(gè)對(duì)象是不是 可迭代對(duì)象或者 是不是迭代器~
使用語法如下:

from collections import Iterable, Iterator
isinstance(str1, Iterable)
isinstance(str1, Iterator)

使用示例:

from collections import Iterable, Iterator
f = open(file='/Users/luyi/tmp/abc', mode='r', encoding='utf-8')
print(isinstance(f, Iterable))     # True
print(isinstance(f, Iterator))      # True

lst = [1, 2, 3]
print(isinstance(lst, Iterable))   # True
print(isinstance(lst, Iterator))   # False

可見文件對(duì)象是可迭代對(duì)象,又是迭代器,而列表僅是可迭代對(duì)象~

迭代器的特性

總結(jié)一下,迭代器有以下 2 個(gè)特性:
1)提供了一種不依賴于索引的取值方式
2)惰性計(jì)算,節(jié)省內(nèi)存

這里的節(jié)省內(nèi)存是指 迭代器在迭代過程中,不會(huì)一次性把可迭代對(duì)象的所有元素都加載到內(nèi)存中,僅僅是在迭代至某個(gè)元素時(shí)才加載該元素,而在這之前或之后,元素可以不存在或者被銷毀。這個(gè)特點(diǎn)就使得迭代器適合用于遍歷一些巨大的 或是 無限的集合。

迭代器的優(yōu)缺點(diǎn)

1)取值不如按照索引取值來的方便(索引可以直接定位某一個(gè)值,迭代器不行,只能一個(gè)一個(gè)地取下去)
2)迭代器只能往后迭代,不能回退(執(zhí)行__next__() 方法 只能向后,不能向前)
3)無法獲取迭代器的長度

python中的生成器

生成器函數(shù) 和 生成器

生成器函數(shù):函數(shù)體內(nèi)包含有yield關(guān)鍵字,該函數(shù)執(zhí)行的結(jié)果就是一個(gè)生成器(generator)。

>>> def foo():
...     print('first----')
...     yield 1
...     print('second----')
...     yield 2
...     print('third----')
...     yield 3
...     print('fouth----')

如上示例中 foo函數(shù)就是一個(gè)生成器函數(shù),而執(zhí)行foo()函數(shù)后,返回的就是一個(gè)生成器對(duì)象。生成器具有 __next__() 方法 和 __iter__(),所以生成器就是一種迭代器~
python迭代器和生成器

調(diào)用該生成器函數(shù)后,返回generator對(duì)象,然后通過調(diào)用 __next__() 方法不斷獲得下一個(gè)返回值:

>>> g = foo()                 # 返回一個(gè)生成器
>>> g
<generator object foo at 0x101fdbe08>
>>> g.__next__()           # 這里也可以使用 next(g) 來替代
first----
1
>>> g.__next__()
second----
2
>>> g.__next__()
third----
3
>>> g.__next__()
fouth----
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在調(diào)用 生成器 的 __next__() 方法時(shí),會(huì)執(zhí)行對(duì)應(yīng)生成器函數(shù)中的內(nèi)容,執(zhí)行過程中,每次遇到 yield 就會(huì)返回 yield 后面的變量(或者表達(dá)式),隨即中斷;再次調(diào)用生成器 的 __next__() 方法,會(huì)從上一次的中斷處繼續(xù)往后執(zhí)行;而最后一次執(zhí)行__next__()方法,后面已經(jīng)沒有 yield,在打印了 'fouth----' 之后就會(huì)拋出 StopIteration 異常~

一般很少使用 __next__() 方法來迭代生成器,而是直接使用for循環(huán)來迭代,且for循環(huán)會(huì)自動(dòng)捕獲 StopIteration 異常:

g = foo()
for i in g:
    print(i)

輸出結(jié)果:
first----
1
second----
2
third----
3
fouth----

 
生成器函數(shù)一般也會(huì)同 for 循環(huán)配合使用,例如使用通配符匹配指定目錄下的文件并打印:

def files(dest_dir = '/Users/luyi/tmp/', end = '*.log'):
    for i in glob.glob(os.path.join(dest_dir, end)):
        yield i

# files() 得到一個(gè)生成器
print(files())       # <generator object files at 0x1021d9500>

for i in files():    # 遍歷這個(gè)生成器
    print i

輸出結(jié)果:
/Users/luyi/tmp/2.log
/Users/luyi/tmp/3.log
/Users/luyi/tmp/1.log

yield功能總結(jié):
1)與return類似,都可以返回值,但不一樣的地方在于 yield 返回多次值,而 return 只能返回一次
2)為函數(shù)封裝好了__iter__() 和 __next__() 方法,把函數(shù)的執(zhí)行結(jié)果做成了迭代器
3)遵循迭代器的取值方式(obj.__next__()),這樣的操作會(huì)觸發(fā)函數(shù)的執(zhí)行,函數(shù)暫停與再繼續(xù)的狀態(tài)都是由 yield 保存(暫停于yield處,下一次的 __next__() 方法執(zhí)行后,會(huì)從 yield 處繼續(xù)往下執(zhí)行)

yield的表達(dá)式形式

>>> def foo():
...     print('start...')
...    while True:
...         x = yield
...         print(x)
... 
>>> g = foo()  # 第一次執(zhí)行生成器,必須是 next 或者 send(None),類似于初始換的操作,即讓程序執(zhí)行至第一個(gè) yield,并中斷~
>>> next(g)
start...
>>> g.send(2)
2
>>> g.send(3)
3
>>> next(g)      # 沒有傳值的情況
None

這里生成器的 send() 方法會(huì)先將值傳遞給 yield,然后由 yield 賦值給 x,賦值完成之后,繼續(xù)往下執(zhí)行,直到再一次遇到y(tǒng)ield。所以 send 的作用和 next 方法相同,還多了一個(gè)賦值功能。

send 的 2個(gè)作用:
1)傳值給 yield,然后由 yield 傳遞給變量(若沒有傳值給 yield,則 yield 會(huì)將 None 賦值給變量)
2)與next相同的功能

上述示例中使用 send 之前,必須對(duì)生成器來一個(gè)類似于初始化的操作:執(zhí)行next 或者 send(None)。為了簡化這個(gè)步驟,這里可以使用裝飾器:

def init(func):            # 這個(gè)裝飾器可以重復(fù)使用(裝飾其它生成器)
    def wrapper(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return wrapper

@init
def foo():
    print('start...')
   while True:
        x = yield
        print(x)

g = foo()
g.send('abc')

yield表達(dá)式一共有4種:
1)yield exp,僅有返回值,exp可以是函數(shù),表達(dá)式等
2)s = yield exp,有返回值,且可以傳入一個(gè)值存入 s 中
3)s = yield,可傳入一個(gè)值,沒有返回值(返回為None)
4)yield,不接受輸入,也沒有返回值(返回為None)

生成器的應(yīng)用

python中的生成器(generator)通常用來實(shí)現(xiàn)協(xié)程,即在執(zhí)行一個(gè)函數(shù)的過程中,中斷當(dāng)前函數(shù),轉(zhuǎn)而去執(zhí)行別的函數(shù),執(zhí)行完成之后,返回來繼續(xù)當(dāng)前函數(shù)的執(zhí)行,整個(gè)過程在一個(gè)線程中完成;也可以換個(gè)角度來進(jìn)行理解,即當(dāng)前函數(shù)的循環(huán)執(zhí)行會(huì)不斷產(chǎn)生數(shù)據(jù),將每一次產(chǎn)生的數(shù)據(jù)交由另一個(gè)函數(shù)做進(jìn)一步的處理,處理完成之后返回,繼續(xù)執(zhí)行當(dāng)前函數(shù)~

下面通過一個(gè)簡單的生產(chǎn)者-消費(fèi)者模型來說明:

def init(func):
    def wrapper(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return wrapper

@init
def consumer():
    res = ''
   while True:
        p = yield res
        if not p:
            continue
        print('Consuming %s...' % p)
        res = 'OK'

def produce(c):
    for i in range(1,5):
        print('producing %s...' % i)
        r = c.send(i)
        print('return status: %s' % r)
    c.close()

c = consumer()
produce(c)

輸出結(jié)果:
producing 1...
Consuming 1...
return status: OK
producing 2...
Consuming 2...
return status: OK
producing 3...
Consuming 3...
return status: OK
producing 4...
Consuming 4...
return status: OK

執(zhí)行流程說明:
1.c = consumer() 拿到的已經(jīng)是初始化后的生成器(即生成器已經(jīng)執(zhí)行了一次next(c));
2.調(diào)用 produce(),生產(chǎn)數(shù)據(jù)之后,通過send(i),將數(shù)據(jù)發(fā)送給 consumer,并且切換到consumer執(zhí)行;
3.consumer 通過 yield 獲取數(shù)據(jù),然后進(jìn)行消費(fèi),最后通過 yield 把處理結(jié)果返回給produce;
4.produce 獲取 consumer 的處理結(jié)果之后,繼續(xù)生產(chǎn)下一次的數(shù)據(jù)~

.................^_^

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享文章:python迭代器和生成器-創(chuàng)新互聯(lián)
新聞來源:http://m.newbst.com/article16/cosegg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作云服務(wù)器網(wǎng)站排名企業(yè)建站標(biāo)簽優(yōu)化網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)