python 中最富爭議的語句就是 yield 語句,yield 語句提供了用戶構造實現生成器(generator)的可能,但由於其語法和函數很相像,所以容易誤用和誤解:
讓我們來看下面一段經典的 yield 語句使用:
1. yield 使用示例
以上是 python 官網中對於fibonacci sequence(斐波那契數列)的一個經典實現,其中的 yield 語句每次返回一個 fibo 數;yield 語句的使用使得 fibo()成為了一個生成器函數,該函數需要實例化出一個生成器對象才能被投入使用,語句f = fibo() 正是在做實例化生成器的步驟,這點很關鍵;有了生成器實例對象,利用生成器對象的 next()方法,可以每次當即計算生成一個 fibo 數,並將其返回。生成器對象內部會記憶 上下文狀態 ,簡單來說就是記憶暫停播放的點,在上述示例中就是記住變量a 和 變量b 的當前值。
生成器對象相比於序列對象(sequence object),例如列表對象,元組對象,字符串對象等的來說,是一種數據的延遲加載方案,可以節約出大量的內存資源,是一種以時間換空間的性能優化策略。下面的示例,能夠體現出yield 生成器對象的這種使用:
2. yield 生成器作為迭代器示例
運行的結果如下顯示:
上述代碼示例中的agen對象作為可迭代對象放入了 for-in語句中,隨著 while 條件滿足的失敗,生成器的生命周期也到了終點,再調用該對象的next()方法,則會拋出StopIteration的異常;從兩次運行的時間耗費長度上來看,顯然 yield 生成器的用時要相對耗時多些,但這是內存節約的代價;deltaNum返回的是完整的列表對象,佔5個整數的內存,而arithmetic僅僅佔用一個整數的內存空間。