python:理解關鍵字—yield

前言

爲了方便追小說更新擼了一個基於scrapy的爬蟲。在實現過程當中使用到了 yield,網上對其的文字描述都很難讓人理解。經過Debug代碼才瞭解調用順序,進而理解了它使用方法。python

概念

理解yield做用

咱們能夠用一個等式來形容其做用: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, ",")
複製代碼

在咱們的預期中,咱們的預期執行順序是

upload successful
這樣的話執行結果應該是這樣:

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.
複製代碼

那麼意味着它的執行順序是這樣:

upload successful
debug後也發現的確如此。

能夠發現,只要執行到yield關鍵字都會先return,在外層執行完畢後,再執行yield以後下一條指令。

啓發

當咱們處理數據量大的事物的時候,能夠效仿關鍵字yield這樣的思路:持有索引或者其餘可檢索的id,在須要的時候再去經過構造器或者其餘工具獲取

相關文章
相關標籤/搜索