Python中yield和yield from的用法


yield

python中yield的用法很像return,都是提供一個返回值,但是yield和return的最大區別在於,return一旦返回,則代碼段執行結束,但是yield在返回值以后,會交出CUP的使用權,代碼段並沒有直接結束,而是在此處中斷,當調用send()或者next()方法之后,yield可以從之前中斷的地方繼續執行。

在一個函數中,使用yield關鍵字,則當前的函數會變成生成器。

下面生成一個斐波那契數列。

def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        yield b
        a,b = b, a+b
        index += 1
  1. 生成器對象
fib = fib(100)
print(fib)


打印出來的結果是一個生成器對象,並沒有直接把我們想要的值打印出來。

  1. next()方法
fib = fib(100)
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

它的執行順序是這樣的,每次yield返回之后,程序將會中斷,當出現next(fib)之后,程序將會從之前中斷的地方繼續執行。 python新版本中,不再提供fib.next()方法。

  1. send()方法

使用send()方法允許我們向生成器中傳值。

import time

def fib(n):
    index = 0
    a = 0
    b = 1

    while index < n:
        sleep = yield b
        print('等待%s秒' %sleep)
        time.sleep(sleep)
        a,b = b, a+b
        index += 1

fib = fib(20)
print(fib.send(None))   # 效果等同於print(next(fib))
print(fib.send(2))
print(fib.send(2))
print(fib.send(2))
print(fib.send(2))

執行順序如下:
首先,創建生成器對象
調用fib.send(None)方法,此處作用與next(fib)相同,程序返回當前b的值1, 程序中斷。
調用fib.send(2)方法,程序被喚醒,將2傳遞給yield之前的變量sleep,程序繼續運行,直到遇到yield將新的b返回,程序再次中斷。
如此繼續下去,直到程序結束。

yield from

前面的都是單一層次的生成器,並沒有嵌套,如果是多個生成器嵌套會怎么樣呢,下面是一個例子。

def fun_inner():
    i = 0
    while True:
        i = yield i

def fun_outer():
    a = 0
    b = 1
    inner = fun_inner()
    inner.send(None)
    while True:
        a = inner.send(b)
        b = yield a

if __name__ == '__main__':
    outer = fun_outer()
    outer.send(None)
    for i in range(5):
        print(outer.send(i))

在兩層嵌套的情況下,值的傳遞方式是,先把值傳遞給外層生成器,外層生成器再將值傳遞給外層生成器,內層生成器在將值反向傳遞給外層生成器,最終yield出結果。如果嵌套的層次更多,傳遞將會越麻煩。

下面是yield from的實現方式:

def fun_inner():
    i = 0
    while True:
        i = yield i

def fun_outer():
    yield from fun_inner()

if __name__ == '__main__':
    outer = fun_outer()
    outer.send(None)
    for i in range(5):
        print(outer.send(i))

效果是一樣的,但是明顯的代碼量減少了,嵌套傳值的時候,並不需要我們手動實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM