爲了方便追小說更新擼了一個基於scrapy的爬蟲。在實現過程當中使用到了 yield,網上對其的文字描述都很難讓人理解。經過Debug代碼才瞭解調用順序,進而理解了它使用方法。python
咱們能夠用一個等式來形容其做用:shell
yeild 函數 = return 生成器(generator) 用同步方式寫異步異步
生成器 = 可迭代的函數scrapy
正常狀況下咱們能夠這樣迭代一個列表函數
# encoding:UTF-8
def call(i):
return i * 2
array = [call(0),call(1),call(2)]
for i in array:
print(i, ",")
複製代碼
打印結果:工具
0 ,
2 ,
4 ,
複製代碼
以上的代碼,適合在數據量小的狀況下運行,假如在海量數據的場景下,這樣的寫法將對內存形成很大的壓力。由於列表內全部數據都同時加載在內存中。spa
而python的生成器則完美的解決了這一問題,它不須要將全部的值同時加載,它只提供了一個生成數據的方式, 並且它是可迭代debug
# encoding:UTF-8
def call(i):
return i * 2
def generator(n):
for i in range(n):
yield call(i)
for i in generator(3):
print(i, ",")
複製代碼
打印結果:code
0 ,
2 ,
4 ,
複製代碼
能夠看到 generator 作的事情很簡單:循環生成了0到2相對應的值。而yield的做用就是提供生成器給外部。cdn
這樣作的好處就在於每次值都是按需生成的,且生成完不會停駐在內存中。
值得一提的就是yield的調用順序也是很清奇的,它的調用順序和咱們常見的簡單的自上而下。 咱們在以上的demo中加入幾行print
# encoding:UTF-8
def call(i):
return i * 2
def generator(n):
for i in range(n):
yield call(i)
print("generate i=", i)
print("end.")
for i in generator(3):
print(i, ",")
複製代碼
在咱們的預期中,咱們的預期執行順序是
這樣的話執行結果應該是這樣:generate i= 0
0 ,
generate i= 1
2 ,
generate i= 2
4 ,
end.
複製代碼
而它的結果運行結果倒是這樣:
0 ,
generate i= 0
2 ,
generate i= 1
4 ,
generate i= 2
end.
複製代碼
那麼意味着它的執行順序是這樣:
debug後也發現的確如此。能夠發現,只要執行到yield關鍵字都會先return,在外層執行完畢後,再執行yield以後下一條指令。
當咱們處理數據量大的事物的時候,能夠效仿關鍵字yield這樣的思路:持有索引或者其餘可檢索的id,在須要的時候再去經過構造器或者其餘工具獲取