茄子在线看片免费人成视频,午夜福利精品a在线观看,国产高清自产拍在线观看,久久综合久久狠狠综合

    <s id="ddbnn"></s>
  • <sub id="ddbnn"><ol id="ddbnn"></ol></sub>

  • <legend id="ddbnn"></legend><s id="ddbnn"></s>

    Python中的生成器和yield詳細介紹
    來源:易賢網(wǎng) 閱讀:1092 次 日期:2015-01-16 14:48:04
    溫馨提示:易賢網(wǎng)小編為您整理了“Python中的生成器和yield詳細介紹”,方便廣大網(wǎng)友查閱!

    列表推導與生成器表達式

    當我們創(chuàng)建了一個列表的時候,就創(chuàng)建了一個可以迭代的對象:

    代碼如下:

    >>> squares=[n*n for n in range(3)]

    >>> for i in squares:

    print i

    0

    1

    4

    這種創(chuàng)建列表的操作很常見,稱為列表推導。但是像列表這樣的迭代器,比如str、file等,雖然用起來很方便,但有一點,它們是儲存在內(nèi)存中的,如果值很大,會很麻煩。

    而生成器表達式不同,它執(zhí)行的計算與列表包含相同,但會迭代的生成結(jié)果。它的語法與列表推導一樣,只是要用小括號來代替中括號:

    代碼如下:

    >>> squares=(n*n for n in range(3))

    >>> for i in squares:

    print i

    0

    1

    4

    生成器表達式不會創(chuàng)建序列形式的對象,不會把所有的值都讀取到內(nèi)存中,而是會創(chuàng)建一個通過迭代并按照需求生成值的生成器對象(Generator)。

    那么,還有沒有其它方法來產(chǎn)生生成器呢?

    例子:斐波那契數(shù)列

    例如有個需求,要生成斐波那契數(shù)列的前10位,我們可以這樣寫:

    代碼如下:

    def fib(n):

    result=[]

    a=1

    b=1

    result.append(a)

    for i in range(n-1):

    a,b=b,a+b

    result.append(a)

    return result

    if __name__=='__main__':

    print fib(10)

    數(shù)字很少時,函數(shù)運行良好,但數(shù)字很多時,問題就來了,顯然生成一個幾千幾萬長度的列表并不是一個很好的主意。

    這樣,需求就變成了:寫一個可以生成可迭代對象的函數(shù),或者說,不要讓函數(shù)一次返回全部的值,而是一次返回一個值。

    這好像與我們的常識相違背,當我們調(diào)用一個普通的Python函數(shù)時,一般是從函數(shù)的第一行代碼開始執(zhí)行,結(jié)束于return語句、異?;蛘吆瘮?shù)結(jié)束(可以看作隱式的返回None):

    代碼如下:

    def fib(n):

    a=1

    b=1

    for i in range(n-1):

    a,b=b,a+b

    return a

    if __name__=='__main__':

    print fib(10)

    >>>

    1 #返回第一個值時就卡住了

    函數(shù)一旦將控制權(quán)交還給調(diào)用者,就意味著全部結(jié)束。函數(shù)中做的所有工作以及保存在局部變量中的數(shù)據(jù)都將丟失。再次調(diào)用這個函數(shù)時,一切都將從頭創(chuàng)建。函數(shù)只有一次返回結(jié)果的機會,因而必須一次返回所有的結(jié)果。通常我們都這么認為的。但是,如果它們并非如此呢?請看神奇的yield:

    代碼如下:

    def fib(n):

    a=1

    yield a

    b=1

    for i in range(n-1):

    a,b=b,a+b

    yield a

    if __name__=='__main__':

    for i in fib(10):

    print i

    >>>

    1

    1

    2

    3

    5

    8

    13

    21

    34

    生成器Generator

    python中生成器的定義很簡單,使用了yield關(guān)鍵字的函數(shù)就可以稱之為生成器,它生成一個值的序列:

    代碼如下:

    def countdown(n):

    while n>0:

    yield n

    n-=1

    if __name__=='__main__':

    for i in countdown(10):

    print i

    生成器函數(shù)返回生成器。要注意的是生成器就是一類特殊的迭代器。作為一個迭代器,生成器必須要定義一些方法,其中一個就是__next__()。如同迭代器一樣,我們可以使用next()函數(shù)(Python3是__next__() )來獲取下一個值:

    代碼如下:

    >>> c=countdown(10)

    >>> c.next()

    10

    >>> c.next()

    9

    每當生成器被調(diào)用的時候,它會返回一個值給調(diào)用者。在生成器內(nèi)部使用yield來完成這個動作。為了記住yield到底干了什么,最簡單的方法是把它當作專門給生成器函數(shù)用的特殊的return。調(diào)用next()時,生成器函數(shù)不斷的執(zhí)行語句,直至遇到y(tǒng)ield為止,此時生成器函數(shù)的”狀態(tài)”會被凍結(jié),所有的變量的值會被保留下來,下一行要執(zhí)行的代碼的位置也會被記錄,直到再次調(diào)用next()繼續(xù)執(zhí)行yield之后的語句。

    next()不能無限執(zhí)行,當?shù)Y(jié)束時,會拋出StopIteration異常。迭代未結(jié)束時,如果你想結(jié)束生成器,可以使用close()方法。

    代碼如下:

    >>> c.next()

    1

    >>> c.next()

    StopIteration

    >>> c=countdown(10)

    >>> c.next()

    10

    >>> c.close()

    >>> c.next()

    StopIteration

    協(xié)程與yield表達式

    yield語句還有更給力的功能,作為一個語句出現(xiàn)在賦值運算符的右邊,接受一個值,或同時生成一個值并接受一個值。

    代碼如下:

    def recv():

    print 'Ready'

    while True:

    n=yield

    print 'Go %s'%n

    >>> c=recv()

    >>> c.next()

    Ready

    >>> c.send(1)

    Go 1

    >>> c.send(2)

    Go 2

    以這種方式使用yield語句的函數(shù)稱為協(xié)程。在這個例子中,對于next()的初始調(diào)用是必不可少的,這樣協(xié)程才能執(zhí)行可通向第一個yield表達式的語句。在這里協(xié)程會掛起,等待相關(guān)生成器對象send()方法給它發(fā)送一個值。傳遞給send()的值由協(xié)程中的yield表達式返回。

    協(xié)程的運行一般是無限期的,使用方法close()可以顯式的關(guān)閉它。

    如果yield表達式中提供了值,協(xié)程可以使用yield語句同時接收和發(fā)出返回值。

    代碼如下:

    def split_line():

    print 'ready to split'

    result=None

    while True:

    line=yield result

    result=line.split()

    >>> s=split_line()

    >>> s.next()

    ready to split

    >>> s.send('1 2 3')

    ['1', '2', '3']

    >>> s.send('a b c')

    ['a', 'b', 'c']

    注意:理解這個例子中的先后順序非常重要。首個next()方法讓協(xié)程執(zhí)行到y(tǒng)ield result,這將返回result的值None。在接下來的send()調(diào)用中,接收到的值被放到line中并拆分到result中。send()方法的返回值就是下一條yield語句的值。也就是說,send()方法可以將一個值傳遞給yield表達式,但是其返回值來自下一個yield表達式,而不是接收send()傳遞的值的yield表達式。

    如果你想用send()方法來開啟協(xié)程的執(zhí)行,必須先send一個None值,因為這時候是沒有yield語句來接受值的,否則就會拋出異常。

    代碼如下:

    >>> s=split_line()

    >>> s.send('1 2 3')

    TypeError: can't send non-None value to a just-started generator

    >>> s=split_line()

    >>> s.send(None)

    ready to split

    使用生成器與協(xié)程

    乍看之下,如何使用生成器和協(xié)程解決實際問題似乎并不明顯。但在解決系統(tǒng)、網(wǎng)絡(luò)和分布式計算方面的某些問題時,生成器和協(xié)程特別有用。實際上,yield已經(jīng)成為Python最強大的關(guān)鍵字之一。

    比如,要建立一個處理文件的管道:

    代碼如下:

    import os,sys

    def default_next(func):

    def start(*args,**kwargs):

    f=func(*args,**kwargs)

    f.next()

    return f

    return start

    @default_next

    def find_files(target):

    topdir=yield

    while True:

    for path,dirname,filelist in os.walk(topdir):

    for filename in filelist:

    target.send(os.path.join(path,filename))

    @default_next

    def opener(target):

    while True:

    name=yield

    f=open(name)

    target.send(f)

    @default_next

    def catch(target):

    while True:

    f=yield

    for line in f:

    target.send(line)

    @default_next

    def printer():

    while True:

    line=yield

    print line

    然后將這些協(xié)程連接起來,就可以創(chuàng)建一個數(shù)據(jù)流處理管道了:

    代碼如下:

    finder=find_files(opener(catch(printer())))

    finder.send(toppath)

    程序的執(zhí)行完全由將數(shù)據(jù)發(fā)送到第一個協(xié)程find_files()中來驅(qū)動,協(xié)程管道會永遠保持活動狀態(tài),直到它顯式的調(diào)用close()。

    總之,生成器的功能非常強大。協(xié)程可以用于實現(xiàn)某種形式的并發(fā)。在某些類型的應(yīng)用程序中,可以用一個任務(wù)調(diào)度器和一些生成器或協(xié)程實現(xiàn)協(xié)作式用戶空間多線程,即greenlet。yield的威力將在協(xié)程,協(xié)同式多任務(wù)處理(cooperative multitasking),以及異步IO中得到真正的體現(xiàn)。

    更多信息請查看IT技術(shù)專欄

    更多信息請查看腳本欄目
    易賢網(wǎng)手機網(wǎng)站地址:Python中的生成器和yield詳細介紹

    2026上岸·考公考編培訓報班

    • 報班類型
    • 姓名
    • 手機號
    • 驗證碼
    關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
    工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)