本文目錄一覽:
- 1、如何理解Python關鍵字yield
- 2、python的關鍵字yield有什麼作用
- 3、python中yield是什麼意思
- 4、python中yield的用法問題
- 5、閑話python 45: 淺談生成器yield
如何理解Python關鍵字yield
當函數被調用時,函數體中的代碼是不會運行的,函數僅僅是返回一個生成器對象。這裡理解起來可能稍微有點複雜。
函數中的代碼每次會在 for循環中被執行,接下來是最難的一部分:
for第一次調用生成器對象時,代碼將會從函數的開始處運行直到遇到 yield為止,然後返回此次循環的第一個值,接著循環地執行函數體,返回下一個值,直到沒有值返回為止。
python的關鍵字yield有什麼作用
yield是python中定義為生成器函數,其本質是封裝了 __iter__和__next__方法 的迭代器;
與return返回的區別:return只能返回一次值,函數就終止了,而yield能多次返回值,每次返回都會將函數暫停,下一次next會從上一次暫停的位置繼續執行;
以下用示例說明:
def test(a,b):
print(“from test(),a+b=%d” %(a+b))
return(“我是return返回的”)
def test_yield(a,b): #函數體中有yield關鍵字,函數就可以稱為生成器函數
print(“from test_yield,a+b=%d” %(a+b))
yield(“我是第一次碰到yield關鍵字返回的”) #程序運行時碰到yield,退出函數體並記錄位置,下次調用跳過之前運行的代碼
print(“from test_yield,a*2=%d” %(a*2))
yield(“我是第二次調用碰到yield關鍵字返回的”)
print(test(11,33))
g = test_yield(11,33)
print(next(g)) #通過next()調用生成器函數
print(next(g)) #第二次調用生成器函數
”’
執行結果:
from test(),a+b=44
我是return返回的
from test_yield,a+b=44
我是第一次碰到yield關鍵字返回的
from test_yield,a*2=22
我是第二次調用碰到yield關鍵字返回的
”’
python中yield是什麼意思
一個帶有 yield 的函數就是一個 generator,它和普通函數不同,生成一個 generator 看起來像函數調用,但不會執行任何函數代碼,直到對其調用 next()(在 for 循環中會自動調用 next())才開始執行。雖然執行流程仍按函數的流程執行,但每執行到一個 yield 語句就會中斷,並返回一個迭代值,下次執行時從 yield 的下一個語句繼續執行。看起來就好像一個函數在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
具體,請參考下以下資料:
python中yield的用法問題
yield就是保存當前程序執行狀態。
你用for循環的時候,每次取一個元素的時候就會計算一次。
用yield的函數叫generator,和iterator一樣,它的好處是不用一次計算所有元素,而是用一次算一次,可以節省很多空間。generator每次計算需要上一次計算結果,所以用yield,否則一return,上次計算結果就沒了。
所以保存列表的說法是完全錯誤的。
閑話python 45: 淺談生成器yield
生成器似乎並不是一個經常被開發者討論的語法,因此也就沒有它的大兄弟迭代器那麼著名。大家不討論它並不是說大家都已經對它熟悉到人盡皆知,與之相反,即使是工作多年的開發者可能對生成器的運行過程還是知之甚少。這是什麼原因導致的呢?我猜想大概有以下幾點原因: (1)運行流程不同尋常,(2)日常開發不需要,(3)常常將生成器與迭代器混淆。 生成器的運行流程可以按照協程來理解,也就是說 返回中間結果,斷點繼續運行 。這與我們通常對於程序調用的理解稍有差異。這種運行模式是針對什麼樣的需求呢? 一般而言,生成器是應用於大量磁碟資源的處理。 比如一個很大的文件,每次讀取一行,下一次讀取需要以上一次讀取的位置為基礎。下面就通過代碼演示具體看看生成器的運行機制、使用方式以及與迭代器的比較。
什麼是生成器?直接用文字描述可能太過抽象,倒不如先運行一段代碼,分析這段代碼的運行流程,然後總結出自己對生成器的理解。
從以上演示可以看出,這段代碼定義了一個函數,這個函數除了yield這個關鍵字之外與一般函數並沒有差異,也就是說生成器的魔法都是這個yield關鍵字引起的。 第一點,函數的返回值是一個生成器對象。 上述代碼中,直接調用這個看似普通的函數,然後將返回值列印出來,發現返回值是一個對象,而並不是普通函數的返回值。 第二點,可以使用next對這個生成器對象進行操作 。生成器對象天然的可以被next函數調用,然後返回在yield關鍵字後面的內容。 第三,再次調用next函數處理生成器對象,發現是從上次yield語句之後繼續運行,直到下一個yield語句返回。
生成器的運行流程確實詭異,下面還要演示一個生成器可以執行的更加詭異的操作:運行過程中向函數傳參。
返回生成器和next函數操作生成器已經並不奇怪了,但是在函數運行過程中向其傳參還是讓人驚呆了。 調用生成器的send函數傳入參數,在函數內使用yield語句的返回值接收,然後繼續運行直到下一個yield語句返回。 以前實現這種運行流程的方式是在函數中加上一個從控制台獲取數據的指令,或者提前將參數傳入,但是現在不用了,send方式使得傳入的參數可以隨著讀取到的參數變化而變化。
很多的開發者比較容易混淆生成器和迭代器,而迭代器的運行過程更加符合一般的程序調用運行流程,因此從親進度和使用熟悉度而言,大家對迭代器更有好感。比如下面演示一個對迭代器使用next方法進行操作。
從以上演示來看,大家或許會認為迭代器比生成器簡單易用得太多了。不過,如果你了解迭代器的實現機制,可能就不會這麼早下結論了。python內置了一些已經實現了的迭代器使用確實方便,但是如果需要自己去寫一個迭代器呢?下面這段代碼就帶大家見識以下迭代器的實現。
在python中,能被next函數操作的對象一定帶有__next__函數的實現,而能夠被迭代的對象有必須實現__iter__函數。看了這麼一段操作,相信大家對迭代器實現的繁瑣也是深有體會了,那麼生成器的實現是不是會讓你覺得更加簡單易用呢?不過千萬別產生一個誤區,即生成器比迭代器簡單就多用生成器。 在實際開發中,如果遇到與大量磁碟文件或者資料庫操作相關的倒是可以使用生成器。但是在其他的任務中使用生成器難免有炫技,並且使邏輯不清晰而導致可讀性下降的嫌疑。 這大概也能解釋生成器受冷落的原因。不過作為一個專業的開發者,熟悉語言特性是分內之事。
到此,關於生成器的討論就結束了。本文的notebook版本文件在github上的cnbluegeek/notebook倉庫中共享,歡迎感興趣的朋友前往下載。
原創文章,作者:IDBEL,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/330552.html