python中yield的用法

昨天看了許多條博客,同時問了大佬一些心中的疑惑,對這個yield心中有了些許的理解,雖然可能沒有理解到他的內涵,但至少在使用時該如何使用仍是有了些許瞭解,所以決定寫出來分享python

首先咱們得了解一個東西叫迭代器,一般的for…in…循環中,in後面是一個數組,這個數組就是一個可迭代對象,相似的還有鏈表,字符串,文件。它能夠是mylist = [1, 2, 3],也能夠是mylist = [x*x for x in range(3)]。 它的缺陷是全部數據都在內存中,若是有海量數據的話將會很是耗內存。他們能夠從內容從中一個一個的讀取,這就是迭代。數組

接着咱們須要瞭解迭代器裏的一個特殊——生成器,生成器也是一個能夠迭代的對象,可是生成器每一個只能迭代一次(至於爲何後面會講),這是他特殊的緣由。由於用的時候才生成。好比 mygenerator = (x*x for x in   range(3)),注意這裏用到了(),它就不是數組,而上面的例子是[]。生成器這裏用的是小括號,而迭代器用的是中括號。函數

好了接下來得講下他們的方法,無論是生成器仍是迭代器,均可以使用他的方法,就是next(這個方法在python2裏面是使用的時候是方法c.next(),在python3裏面變爲了函數next(c)),可是因爲迭代器能夠自動進行,至關於裏面已經內嵌了這個方法,生成一個迭代器他能夠自動日後迭代,可是生成器不同,生成一個生成器的時候,他是定在初始狀態的,這就須要咱們的next來一步一步推進他們。他們還有一種方法是send(),這個至關於在next功能的基礎上,再加了一個傳遞的功能,他能夠傳遞參數給yield表達式,因此send(None)就至關於next參數。spa

如今咱們能夠來談談yield了,其實yield就至關於一個return,只是return返回的是值,可是yield返回的是生成器,除了這點其餘都同樣,因此return也好yield也好都只能用在函數中,不要出現這種代碼了:code

for i in range(5):
    return i

因此要試驗yield要在函數裏實驗,咱們能夠試着構造一個生成器:對象

def y_test(x):
    for i in range(x):
        yield i
        print(i)
y_test(3)

咱們試着輸出結果,卻發現沒有輸出,這是由於生成了一個生成器,並且生成的生成器是在初始狀態,我們還沒給他下指令他就不會開始生成,因此如今咱們給他一個指令blog

def y_test(x):
    for i in range(x):
        yield i
        print(i)
y_test(3)
c = y_test(3)
next(c)

誒,咱們如今改造了後爲何仍是顯示沒有輸出,如今生成器是生成了但別忘了這是一個至關於return的函數,他實際上已經把值傳進了內存,可是沒有顯示出來,咱們能夠用一個print把他顯示出來內存

def y_test(x):
    for i in range(x):
        yield i
        print(i)
y_test(3)
c = y_test(3)
print(next(c))

如今咱們就會看到它顯示出來了(range這個函數生成了從1到n-1得數,好比range(5)生成了0.1.2.3.4)ci

好,那麼接下來你可能又會有問題了,爲何這個只生成了第一個數啊,不該該是遍歷把全部的輸出來嗎,這就是yield的做用了,這是由於生成了生成器,咱們next他一次,他也就只會往前走一次,第二次就不走了,那咱們就再來一次next看看會怎樣:字符串

def y_test(x):
    for i in range(x):
        yield i
        print(i)
y_test(3)
c = y_test(3)
print(next(c))
print(next(c))

 

這時候出現了三個值,這就要繼續解釋yield的緣由了,每次咱們使用一次next,他都會執行到第一個yield結束的位置,第二次用next推進他執行時,他就會從上一個yield執行完成的位置開始執行到下一個yield執行完成,在這裏是在for循環裏,下一個yield就是第二個循環裏的yield,雖然是同樣的語句,可是他們所在的循環次數不同,因此yield就至關於返回值的同時,記住當前運行到的位置,下一次運行就從上一次運行到的位置開始運行,這也是爲何他只能遍歷一遍的緣由,由於在第二個next執行的時候,第一個next裏的內容已經被拋掉了,內存裏只有第二個yield執行的內容。

咱們能夠再看一例子來加深理解:

def f(x):
    for i in range(x):
        yield i
        print (i)
        yield i+1
        
c = f(5)
print(next(c))  
print(next(c)) 
print(next(c)) 

根據上文的理解會輸出四個值

符合前面的猜測,最後讓咱們來用一個斐波那契數列的例子來結束全文吧:

def fib(x):
    yield 1
    a,b = 1,1
    while x:
        a,b = b,a+b
        yield a
        x=x-1         
for i in fib(5):
    print(i)




>>>runfile('F:/Python/exercise/pygame/yield_text.py', wdir='F:/Python/exercise/pygame')
1
1
2
3
5
8
相關文章
相關標籤/搜索