從python的yield提及

前段時間在讀trac 中wiki模塊的源碼的時候,發現了不少地方都使用了yiled這一關鍵詞,html

感受是在須要返回某個值的地方經過yield來代替return,python

不是很明白其用法,因此仔細研究下。函數

 

一個使用了yiled關鍵字的函數就再也不是一個普通的函數了,而是一個生成器函數(generator function),spa

當函數被調用的時候將返回一個迭代器(iterator)。htm

 

因此下面將分別講解迭代器和生成器這兩個概念。對象

 

一. 迭代器(Iterator)

 

 寫道
迭代器是一個對象,它實現了迭代器協議,
通常須要實現以下兩個方法
1)next方法
返回容器的下一個元素
2)__iter__方法
返回迭代器自身

 

 

對於for語言你們可能都不陌生,咱們不少時候須要對一些容器對象進行遍歷就會使用到for循環:utf-8

 

Python代碼   收藏代碼
  1. l=[0,1,2,3,4,5,6]  
  2. for i in l:  
  3.     print i  

 

l是一個type爲list的對象,這段for-in代碼在運行的時候實際上是調用了l的__iter__()函數,返回了一個實現了__next__()或next()(各個版本的python可能不同,我試驗的時候所使用的版本爲2.6.2)的迭代器對象,每循環一次就會經過next取下一個元素。ci

 

固然咱們徹底沒有必要先把全部的元素都算出來放到一個list裏或者其餘容器類裏進行循環,這樣比較浪費空間。get

咱們能夠直接建立本身的一個迭代器。generator

 

Python代碼   收藏代碼
  1. # -*- coding: utf-8 -*-  
  2.   
  3. '''''Fibonacci iterator'''  
  4.   
  5. class Fib:  
  6.     '''''一個能夠生成Fibonacci 數列的迭代器'''  
  7.   
  8.     def __init__(self, max):  
  9.         self.max = max  
  10.   
  11.     def __iter__(self):  
  12.         self.a = 0  
  13.         self.b = 1  
  14.         return self  
  15.   
  16.     def next(self):  
  17.         fib = self.a  
  18.         if fib > self.max:  
  19.             raise StopIteration  
  20.         self.a, self.b = self.b, self.a + self.b  
  21.         return fib  

 

 

定義好了這個Fibonacci迭代器,咱們就能夠來使用它了。

 

 

Python代碼   收藏代碼
  1. from fibonacci2 import Fib  
  2. for n in Fib(1000):  
  3.     print n  

 

當調用Fib(1000)的時候,將生成一個迭代器對象,每一次循環都將調用一次next取到下一個值。

因此咱們能夠看出迭代器有一個很核心的東西就是在循環中,迭代器能夠記住以前的狀態。

 

 

二.生成器

 

前面咱們說了,任何使用了yield關鍵字的函數都再也不是普通的函數了,咱們仍是來看實例吧,這樣比較容易理解

 

 

Python代碼   收藏代碼
  1. def fib(max):  
  2.     a, b = 0, 1            
  3.     while a < max:  
  4.         yield a            
  5.         a, b = b, a + b    

   這裏簡單的幾行代碼就實現了上面的迭代器類那麼一大堆代碼所實現的功能

 

   使用的時候和上面很相似:

 

 

Python代碼   收藏代碼
  1. from fibonacci import fib  
  2. for n in fib(1000):  
  3.     print n  

 

引文fib函數使用了yield因此它是一個生成器函數,當咱們調用fib(1000)的時候它實際上是返回了一個迭代器,且這個迭代器能夠控制生成器函數的運行。

咱們經過這個返回的迭代器的動做控制fib這個生成器函數的運行。

每當調用一次迭代器的next函數,生成器函數運行到yield之處,返回yield後面的值且在這個地方暫停,全部的狀態都會被保持住,直到下次next函數被調用,或者碰到異常循環退出。

 

因此生成器的概念仍是很簡單的。

 

三.總結

 

1.for-in語句在底層都是對一個迭代器對象進行操做的

2.使用了yield關鍵字的函數就是一個生成器函數,被調用的時候生成一個能夠控制本身運行的迭代器。

相關文章
相關標籤/搜索