Python yield的功能淺析
阿新 • • 發佈:2018-11-07
yield
的功能類似於return
,但是不同之處在於它返回的是生成器
。
生成器
生成器是通過一個或多個yield
表示式構成的函式,每一個生成器都是一個迭代器(但是迭代器不一定是生成器)。
如果一個函式包含yield
關鍵字,這個函式就會變為一個生成器。
生成器並不會一次返回所有結果,而是每次遇到yield
關鍵字後返回相應結果,並保留函式當前的執行狀態,等待下一次的呼叫。
由於生成器也是一個迭代器,那麼它就應該支援next
方法來獲取下一個值。
基本操作
for item in items: div=item.find('a').attr('href') info=item.find('a').text() yield div,info # return { # 'div': div, # 'info ': info # }
返回迭代器,然後 使用for迴圈輸出
# 通過`yield`來建立生成器
def func():
for i in xrange(10);
yield i
# 通過列表來建立生成器
[i for i in xrange(10)]
# 呼叫如下 >>> f = func() >>> f # 此時生成器還沒有執行 <generator object func at 0x7fe01a853820> >>> f.next() # 當i=0時,遇到yield關鍵字,直接返回 0 >>> f.next() # 繼續上一次執行的位置,進入下一層迴圈 1 ... >>> f.next() 9 >>> f.next() # 當執行完最後一次迴圈後,結束yield語句,生成StopIteration異常 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>>
除了next
函式,生成器還支援send
函式。該函式可以向生成器傳遞引數。
>>> def func():
... n = 0
... while 1:
... n = yield n #可以通過send函式向n賦值
...
>>> f = func()
>>> f.next() # 預設情況下n為0
0
>>> f.send(1) #n賦值1
1
>>> f.send(2)
2
>>>
應用
最經典的例子,生成無限序列。
常規的解決方法是,生成一個滿足要求的很大的列表,這個列表需要儲存在記憶體中,很明顯記憶體限制了這個問題。
def get_primes(start):
for element in magical_infinite_range(start):
if is_prime(element):
return element
如果使用生成器就不需要返回整個列表,每次都只是返回一個數據,避免了記憶體的限制問題。
def get_primes(number):
while True:
if is_prime(number):
yield number
number += 1
yield常見用法:該關鍵字用於函式中會把函式包裝為generator。然後可以對該generator進行迭代: for x in fun(param).
按照我的理解,可以把yield的功效理解為暫停和播放。
在一個函式中,程式執行到yield語句的時候,程式暫停,返回yield後面表示式的值,在下一次呼叫的時候,從yield語句暫停的地方繼續執行,如此迴圈,直到函式執行完。
擴充套件:
next函式與send函式很相似,都能獲得生成器的下一個yield後面表示式的值,不同的是send函式可以向生成器傳參。
yield from:封裝包含yield的函式,使得子函式也為一個generator.