標籤:

黃哥漫談Python 生成器。

何為生成器(Generators)

下面的黃哥用大白話說明。

當Python 函數不用return 返回值,用yield關鍵字的時候,函數的返回值為生成器對象。

圖中代碼,函數沒有用return 返回值,用yield 輸出值,函數的調用返回值為生成器對象,

生成器對象,用p.next()方法返回一個值,函數執行暫停,下次再調用next()方法時,從

暫停處開始執行,print 輸出值。再執行第二個yield 返回值。

像上面函數的返回值為生成器對象的函數叫做生成器函數。

生成器是一個可迭代對象,可以用for循環迭代。

特別需要注意的是,初學者容易出現的一個錯誤是,生成器用next()方法,到最後一個yield

返回值時,再用一次,會報錯誤StopIteration。

下面圖片中p是生成器,用了二次next()方法,相當於返回值都返回完了,再循環迭代沒有輸出。見過初學者一直問為啥這樣,黃哥說「你可以想像成指針」前面已經指到尾部了。所以

for 循環 沒有輸出。

增強的生成器,有send()和close()方法。

增強的生成器中,除yield可以輸出值,也可以從外部send值到生成器內部。這個時候,yield 是表達式,可以輸出值,也可以接收值賦值給其他變數。

有近一步學習的,請看

PEP 342 -- Coroutines via Enhanced Generators

python.org/dev/peps/pep

下面講講生成器實例代碼。

1、利用生成器生成可以無限取值的斐波拉切函數

#!/usr/bin/env python# -*- coding: utf-8 -*-# Author: 黃哥python培訓 qq:1465376564def fib(): a, b = 0, 1 while True: yield a a, b = b, a + bp = fib()print [p.next() for i in xrange(101)]

2、求PI值。

#!/usr/bin/env python# -*- coding: utf-8 -*-# Author: 黃哥python培訓 qq:1465376564"""1 - 1/3 + 1/5 - 1/7 + ..."""def pi_series(): total = 0 i = 1.0 j = 1 while True: total = total + j / i yield 4 * total i += 2 j = j * -1def main(g, n): for i in range(n): yield g.next()if __name__ == __main__: print list(main(pi_series(), 8))#[4.0, 2.666666666666667, 3.466666666666667, 2.8952380952380956, 3.3396825396825403, 2.9760461760461765, 3.2837384837384844, 3.017071817071818]

3、生成器處理大日誌文本文本。

# coding:utf-8import timestart_time = time.time()def find_ip(path): for line in open(path): s = line.find("Sogou web spider) if s >= 0: yield line[:s].strip()p = find_ip("bigfile.txt")p = list(set(list(p)))for item in p: print itemprint time.time() - start_time, "seconds"

4、生成器函數也可以玩遞歸。

#!/usr/bin/env python# -*- coding: utf-8 -*-# Author: 黃哥python培訓 qq:1465376564def spread_list(lst): tmp = [] for item in lst: if isinstance(item, list): tmp = spread_list(item) for item2 in tmp: yield item2 else: yield iteml = [1, 2, 3, 4, 5, [6], [7, 8, [9, [10]]]]l2 = [[3, 7, [9, 6]], [2, [3, 4], 10], 99, 28]l3 = []l4 = [3, 4, 5, 8]lst = spread_list(l)print list(lst)lst = spread_list(l2)print list(lst)lst = spread_list(l3)print list(lst)lst = spread_list(l4)print list(lst)# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]# [3, 7, 9, 6, 2, 3, 4, 10, 99, 28]# []# [3, 4, 5, 8]

-------------待續


推薦閱讀:

Python數據分析模塊 | pandas做數據分析(二):常用預處理操作
Python中list與collections.abc.Sequence是什麼關係?
Python爬蟲利器之PyQuery的用法
擁抱開放 - RQAlpha,開源的Python策略、回測引擎
學Python web開發框架到什麼程度可以找到開發的工作?

TAG:Python |