python中yield的用法介紹

yield是什麼

yield是python中構造生成器的一個關鍵詞,它被使用在一個函數內,不可以在函數外使用。yield所在的函數被調用時返回的是一個對象,該對象通過next方法被訪問其中的數據,而這些數據正是yield關鍵詞後面的數據。下面結合用法來更深入瞭解yield。

yield怎麼用

yield必須在函數內使用。一個例子如下:

def func():
    print("starting-----")
    num=0
    while num<10:
        num=num+1
        yield num

這個函數做了什麼?它產生了從1到10是個數字。誰產生的,怎麼產生的?yield num這句話產生的。那麼怎麼訪問這十個數字呢。我們說了,yield所在函數被調用返回的是對象,那麼就從這個對象上下文章。

gen=func()
print("access gen")
for g in gen:
    print(g)

輸出結果

access gen
starting-----
1
2
3
4
5
6
7
8
9
10

當創建對象gen,也就是調用包含yield的函數func時,程序執行到yield所在的位置。當進一步訪問gen中的g時,程序進一步執行,獲得yield關鍵詞後面的數據,依次進行。這樣的話,可以把yield看做“return”。
下面再看一個例子

def s():
    print('study yield')
    m = yield 5
    print(m)
    d = yield 16
    print(str(d)+'llll')

我們不運行結果,先分析一下,這個函數發生了什麼?這裏有兩個yield,可以認爲函數s可以返回兩個數字5 和16.我們通過實例來分析一下:

gen=s()
print('xxxxxxxxxxxx')
for g in gen:
    print(g)

返回結果如下:

xxxxxxxxxxxx
study yield
5
None
16
Nonellll

可以看到在print(m)時返回的是None,這是爲什麼?原因在於yield相當於return。把m通過yieldreturn了,當然沒有數據。

c = s()
print( next(c)  )# 相當於send(None)
f=c.send('Fighting!')  # (yield 5)表達式被賦予了'Fighting!'
print(f)
print('-----------')

運行結果

study yield
5
Fighting!
16
-----------

這裏next©相當於運行到下一個yield。而如果用send的話,開始執行的時候,先接着上一次(yield)執行,先把send的值賦值給了當前數值,然後執行next的作用,遇見下一回的yield,return出結果後結束。
從這裏看到,next相當於對函數進行單步調試,而yield則是斷點,每nest一次,則程序運行到斷點,並輸出斷點當前的變量值。而send相當於修改斷點處的值,然後運行到下一個斷點。
那麼當所有斷點運行完了,再next會發什麼。我們在上面代碼增加兩個如下所示:

c = s()
print( next(c)  )# 相當於send(None)
print('************')
f=c.send('Fighting!')  # (yield 5)表達式被賦予了'Fighting!'
print(f)
print('-----------')
ff=c.send("hello")
print(ff)

返回結果如下:

study yield
5
************
Fighting!
16
-----------
hellollll
    ff=c.send("hello")
StopIteration

發生報錯, ff=c.send(“hello”) StopIteration。這說明當不存在下一個yield再進行next或者send時,程序出錯。

yield可以幹什麼用

yield是生成器,可以節省內存空間。爲什麼用這個生成器,是因爲如果用List的話,會佔用更大的空間,比如說取0,1,2,3,4,5,6…1000。用第一個例子的方法則節省不少內存空間。

def compute(a,b):
    return a*a+2*a+b

def listc(i,j):
    result=[]
    while i<5:
        result.append(compute(i,j))
        i=i+1
    return result
list_result=listc(0,1)
for ll in list_result:
    print(ll)

print('xxxxxxxxxxx')

def gen(i,j):
    while i<5:
        yield compute(i,j)
        i=i+1
gen=gen(0,1)
for g in gen:
    print(g)

相比於list.append,yield更能省空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章