python 理解關鍵字 yield

2021-09-11 14:48:12 字數 1998 閱讀 4941

為了方便追**更新擼了乙個基於scrapy的爬蟲。在實現過程中使用到了yield,網上對其的文字描述都很難讓人理解。通過debug**才了解呼叫順序,進而理解了它使用方法。

我們可以用乙個等式來形容其作用:

yeild 函式 = return 生成器(generator)用同步方式寫非同步

生成器 = 可迭代的函式

正常情況下我們可以這樣迭代乙個列表

# encoding:utf-8

defcall

(i):

return i * 2

array = [call(0),call(1),call(2)]

for i in array:

print(i, ",")

複製**

列印結果:

0 ,

2 ,4 ,

複製**

以上的**,適合在資料量小的情況下執行,假如在海量資料的場景下,這樣的寫法將對記憶體造成很大的壓力。因為列表內所有資料都同時載入在記憶體中。

而python的生成器則完美的解決了這一問題,它不需要將所有的值同時載入,它只提供了乙個生成資料的方式, 而且它是可迭代

# encoding:utf-8

defcall

(i):

return i * 2

defgenerator

(n):

for i in range(n):

yield call(i)

for i in generator(3):

print(i, ",")

複製**

列印結果:

0 ,

2 ,4 ,

複製**

可以看到 generator 做的事情很簡單:迴圈生成了0到2相對應的值。而yield的作用就是提供生成器給外部。

這樣做的好處就在於每次值都是按需生成的,且生成完不會停駐在記憶體中。

值得一提的就是yield的呼叫順序也是很清奇的,它的呼叫順序和我們常見的簡單的自上而下。 我們在以上的demo中加入幾行print

# encoding:utf-8

defcall

(i):

return i * 2

defgenerator

(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,在需要的時候再去通過構造器或者其他工具獲取

this關鍵字理解

public class test implements runnable synchronized void m1 throws interruptedexception synchronized void m2 throws interruptedexception override publi...

Python 關鍵字 yield 的理解

為了更好地理解關鍵字yield的用法,首先需要理解迭代器 iterator 與生成器 generator 的區別。當建立列表中的元素時,我們可以使用for迴圈 myiterator x x for x in range 3 print myiterator 0,1,4 因此我們稱列表是可迭代的 it...

C virtual關鍵字理解

在c 語言中,從 到程式的執行,要經歷編譯和連線,針對這兩個不同的階段,c 設計了不同的機制,其中vitual和inline就是區分編譯器工作和鏈結器工作的標誌 inline很容易理解,生命為inline的函式在編譯階段即被展開成 而非inline的函式採用執行時鏈結的方式處理 vitual關鍵字,...