真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python學(xué)習(xí):迭代器與生成器

1.生成器

如果創(chuàng)建一個(gè)有很多元素的列表,但是只需要訪問前幾個(gè)元素,后面的元素占著的空間就白白浪費(fèi)了

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供喀什網(wǎng)站建設(shè)、喀什做網(wǎng)站、喀什網(wǎng)站設(shè)計(jì)、喀什網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、喀什企業(yè)網(wǎng)站模板建站服務(wù),10余年喀什做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

在循環(huán)的過程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list,從而節(jié)省大量的空間。

在Python中,這種一邊循環(huán)一邊計(jì)算的機(jī)制,稱為生成器:generator。

要?jiǎng)?chuàng)建一個(gè)generator,有很多種方法

第一種方法很簡單,只要把一個(gè)列表生成式的[]改成(),就創(chuàng)建了一個(gè)generator:

L = [x * x for x in range(10)]
g = (x * x for x in range(10))
print(L)#
print(g)

輸出

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
 at 0x00000CA6AC0>

可以直接打印出list的每一個(gè)元素,但怎么打印出generator的每一個(gè)元素

print(next(g))
print(next(g))

輸出

0
1

如果要一個(gè)一個(gè)打印出來,可以通過next()函數(shù)獲得generator的下一個(gè)返回值:

generator保存的是算法,比如我要知道計(jì)算第四次的值,next要調(diào)用四次,這太麻煩了

for n in g:
    print(n)

輸出

0
1
4
9
16
25
36
49
64
81

如果要計(jì)算很多次,不斷調(diào)用next實(shí)在是太變態(tài)了,正確的方法是使用for循環(huán),generator也是可迭代對(duì)象,如果某些算法用列表生成式的for循環(huán)無法實(shí)現(xiàn),還可以用函數(shù),比如著名的斐波拉契數(shù)列(Fibonacci)

def fib(max):
    n,a ,b = 0,0,1#n是用來控制迭代的次數(shù)
    while n < max:
        yield b
        a,b = b,a+b
        n = n+1
    return 'done'

如果一個(gè)函數(shù)定義中包含yield關(guān)鍵字,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè)generator:

函數(shù)是順序執(zhí)行,遇到return語句或者最后一行函數(shù)語句就返回

在調(diào)用生成器運(yùn)行的過程中,每次遇到 yield 時(shí)函數(shù)會(huì)暫停并保存當(dāng)前所有的運(yùn)行信息,返回 yield 的值, 并在下一次執(zhí)行 next() 方法時(shí)從當(dāng)前位置繼續(xù)運(yùn)行

def add():
    print('step 1')
    yield 1
    print('step 2')
    yield (3)
    print('step 3')
    yield (5)

在調(diào)用該generator時(shí),首先要生成一個(gè)generator對(duì)象,然后用next()函數(shù)不斷獲得下一個(gè)返回值:

o = add()
print(next(o))
print(next(o))
print(next(o))

輸出

step 1
1
step 2
3
step 3
5

通過next調(diào)用時(shí),遇到y(tǒng)ield就停下了,再次調(diào)用在中斷的地方繼續(xù)往下執(zhí)行

for n in add():
    print(n)

輸出

step 1
1
step 2
3
step 3
5

同樣的,把函數(shù)改成generator后,基本上從來不會(huì)用next()來獲取下一個(gè)返回值,而是直接使用for循環(huán)來迭代

要實(shí)驗(yàn)for需要把上面三次調(diào)用的代碼刪除,因?yàn)槿握{(diào)用已經(jīng)把函數(shù)全部執(zhí)行完了,不會(huì)再去執(zhí)行了。

但是用for循環(huán)調(diào)用generator時(shí),發(fā)現(xiàn)拿不到generator的return語句的返回值

如果想要拿到返回值,必須捕獲StopIteration錯(cuò)誤,返回值包含在StopIteration的value中:

g = fib(6)
while True:
    try:
        x = next(g)
        print('g:',x)
    except StopIteration as e:
        print('Generator return value:',e.value)
        break

generator的工作原理,它是在for循環(huán)的過程中不斷計(jì)算出下一個(gè)元素,并在適當(dāng)?shù)臈l件結(jié)束for循環(huán)。對(duì)于函數(shù)改成的generator來說,遇到return語句或者執(zhí)行到函數(shù)體最后一行語句,就是結(jié)束generator的指令,for循環(huán)隨之結(jié)束

注意區(qū)分普通函數(shù)和generator函數(shù),普通函數(shù)調(diào)用直接返回結(jié)果

generator函數(shù)的“調(diào)用”實(shí)際返回一個(gè)generator對(duì)象

2.迭代器

凡是可作用于for循環(huán)的對(duì)象都是Iterable類型;比如list,tuple,dict,set,str,generator等

判斷是否為Iterable類型

from collections import Iterable

print(isinstance([], Iterable))

輸出

True

凡是可作用于next()函數(shù)的對(duì)象都是Iterator類型,它們表示一個(gè)惰性計(jì)算的序列;

直到最后拋出StopIteration錯(cuò)誤表示無法繼續(xù)返回下一個(gè)值了。

可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterator對(duì)象,生成器都是Iterator對(duì)象

from collections import Iterator
print(isinstance((x for x in range(10)), Iterator))

輸出

True

集合數(shù)據(jù)類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個(gè)Iterator對(duì)象。

'''
學(xué)習(xí)中遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流群:
尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書!
'''
isinstance(iter([]), Iterator)
isinstance(iter('abc'), Iterator)
list=[1,2,3,4]
it = iter(list)
print(next(it))
print(next(it))
#迭代器也可以用常規(guī)for語句進(jìn)行遍歷
for x in it:
    print('當(dāng)前計(jì)算:',x)#上面調(diào)用了兩次,所以這邊會(huì)接著上一次繼續(xù)下去,只會(huì)打印兩句,如果上面只
    #調(diào)用一次,這里會(huì)調(diào)用三次

輸出

1
2
當(dāng)前計(jì)算: 3
當(dāng)前計(jì)算: 4

3.總結(jié)

凡是可作用于for循環(huán)的對(duì)象都是Iterable類型 可迭代對(duì)象

凡是可作用于next()函數(shù)的對(duì)象都是Iterator類型,它們表示一個(gè)惰性計(jì)算的序列

集合數(shù)據(jù)類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個(gè)Iterator對(duì)象

Python的for循環(huán)本質(zhì)上就是通過不斷調(diào)用next()函數(shù)實(shí)現(xiàn)的

比較使用list和generator保存斐波拉契數(shù)列運(yùn)算結(jié)果的的區(qū)別

通過返回 List 能滿足復(fù)用性的要求,但是當(dāng)max函數(shù)運(yùn)行占用的內(nèi)存會(huì)隨著max的增大而增大

def fab(max):
    n, a, b = 0, 0, 1
    L = []
    while n < max:
        L.append(b)
        a, b = b, a + b
        n = n + 1
    return L
for n in fab(5):
    print(n)

輸出

1
1
2
3
5

一個(gè)帶有 yield 的函數(shù)就是一個(gè) generator,它和普通函數(shù)不同,生成一個(gè) generator 看起來像函數(shù)調(diào)用,但不會(huì)執(zhí)行任何函數(shù)代碼,直到對(duì)其調(diào)用 next()(在 for 循環(huán)中會(huì)自動(dòng)調(diào)用 next())才開始執(zhí)行。雖然執(zhí)行流程仍按函數(shù)的流程執(zhí)行,但每執(zhí)行到一個(gè) yield 語句就會(huì)中斷,并返回一個(gè)迭代值,下次執(zhí)行時(shí)從 yield 的下一個(gè)語句繼續(xù)執(zhí)行??雌饋砭秃孟褚粋€(gè)函數(shù)在正常執(zhí)行的過程中被 yield 中斷了數(shù)次,每次中斷都會(huì)通過 yield 返回當(dāng)前的迭代值。

yield 的好處是顯而易見的,把一個(gè)函數(shù)改寫為一個(gè) generator 就獲得了迭代能力,比起用類的實(shí)例保存狀態(tài)來計(jì)算下一個(gè) next() 的值,不僅代碼簡潔,而且執(zhí)行流程異常清晰。

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b  # 使用 yield
        # print b
        a, b = b, a + b
        n = n + 1
for n in fab(5):
    print(n)

輸出

1
1
2
3
5

當(dāng)前題目:Python學(xué)習(xí):迭代器與生成器
URL標(biāo)題:http://weahome.cn/article/dsogess.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部