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更能省空間。