成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

重新認識生成器Generator

開發 前端
我們知道,函數體包含 yield 關鍵字的函數不是一個普通函數。這種函數叫做 生成器 ( generator ),一般用于循環處理結構,應用得當可以極大優化內存使用效率。

 [[395138]]

本文轉載自微信公眾號「小菜學編程」,作者fasionchan。轉載本文請聯系小菜學編程公眾號。

基本用法

我們知道,函數體包含 yield 關鍵字的函數不是一個普通函數。這種函數叫做 生成器 ( generator ),一般用于循環處理結構,應用得當可以極大優化內存使用效率。例如,設計一個函數,打開文件并將每一行轉成大寫并返回:

  1. def read_file_upper(path): 
  2.     lines = [] 
  3.     with open(path) as f: 
  4.         for line in f: 
  5.             lines.append(line.upper()) 
  6.     return lines 

這個版本的函數,在內部創建了一個 list 對象,用于保存轉換結果。for 循環則遍歷文件每一行,將其轉成大寫并追加到列表中。這樣一來,文件中的每一行均需要保存在列表中,如果文件很大,內存開銷可想而知。

我們可以借助 yield 關鍵字,將 read_file_upper 函數改成生成器版本。函數主體邏輯沒有任何變化,只是將每行數據的處理結果通過 yield 逐個返回,而不是收集到 list 對象后再返還。

  1. def iter_file_upper(path): 
  2.     with open(path) as f: 
  3.         for line in f: 
  4.             yield line.upper() 

如果現在有一個文本文件 data.txt ,里面包含以下內容:

  1. hello, world 
  2. life is short, use python 
  3. my wechat id is: coding-fan 
  4. bye 

用 iter_file_upper 生成器,我們可以這樣對它進行處理:

  1. >>> for line in iter_file_upper('text.txt'): 
  2. ...     print(line.strip()) 
  3. HELLO, WORLD 
  4. LIFE IS SHORT, USE PYTHON 
  5. MY WECHAT ID IS: CODING-FAN 
  6. BYE 

iter_file_upper 生成器用法與 read_file_upper 函數大致相同,但它不會一次性拿住文件所有數據行,而是逐行處理、逐個返回,這樣便將內存使用量降到最低。

行為觀察

那么,生成器為什么會有這樣的奇效呢?我們接著觀察:

  1. >>> g = iter_file_upper('text.txt'
  2. >>> g 
  3. <generator object iter_file_upper at 0x103becd68> 

我們調用 iter_file_upper 后,得到一個生成器對象,而不是文件處理結果,這時 iter_file_upper 還未開始執行。

當我們調用 next 函數從生成器接收下一個數據時,iter_file_upper 開始執行并在 yield 處停下來,并把第一行的處理結果返回給我們:

  1. >>> next(g) 
  2. 'HELLO, WORLD\n' 

這時,生成器處于暫停狀態,沒有我們的指令,它不會接著處理第二行數據。

當我們再次執行 next 函數時,生成器再次恢復執行,處理下一行數據并在 yield 處再次暫停:

  1. >>> next(g) 
  2. 'LIFE IS SHORT, USE PYTHON\n' 

生成器記住了自己的執行進度,每次調用 next 函數,它總是處理并生產下一個數據,完全不用我們瞎操心:

  1. >>> next(g) 
  2. 'MY WECHAT ID IS: CODING-FAN\n' 
  3. >>> next(g) 
  4. 'BYE\n' 

當 iter_file_upper 代碼邏輯執行完畢,它將給 next 拋一個異常,以此通知調用者它已經結束了:

  1. >>> next(g) 
  2. Traceback (most recent call last): 
  3.   File "<stdin>", line 1, in <module> 
  4. StopIteration 

因此,我們可以簡單認為 for-in 循環在 Python 虛擬機內部是這樣實現的:

  • 不斷調用 next 函數讓生成器產出數據;
  • 直到生成器拋出 StopIteration 異常;

在經典的線程模型中,每個線程有一個獨立的執行流,只能執行一個任務。如果一個程序需要同時處理多個任務,可以借助 多進程 或者 多線程 技術。假設一個站點需要同時服務多個客戶端連接,可以為每個連接創建一個獨立的線程進行處理。

不管線程還是進程,切換時都會帶來巨大的開銷:用戶態/內核態切換、執行上下文保存和恢復、CPU緩存刷新等等。因此,用線程或進程來驅動小任務的執行,顯然不是一個理想的選擇。

那么,除了線程和進程,還有其他解決方案嗎?

 

責任編輯:武曉燕 來源: 小菜學編程
相關推薦

2022-03-03 08:30:41

GeneratorES6函數

2014-01-06 11:23:54

Mesos設計架構

2016-11-07 11:34:28

數據可視化大數據

2016-12-13 15:41:40

JavaHashMap

2019-10-31 13:40:52

JavaPHP編程語言

2019-02-24 21:27:26

物聯網網關物聯網IOT

2019-09-02 08:53:46

程序員

2021-11-11 05:00:02

JavaMmap內存

2020-09-17 07:08:04

TypescriptVue3前端

2017-01-03 17:22:16

公共云安全

2010-02-25 09:57:35

2012-06-26 11:11:44

架構師

2022-03-04 09:28:29

代碼訪問者模式軟件開發

2022-09-08 13:58:39

Spring高并發異步

2019-01-18 13:32:16

2015-03-19 10:15:54

程序員價值程序員價值

2012-01-11 09:12:25

程序員

2022-10-09 11:46:55

機器人人工智能

2019-04-15 14:32:11

2009-11-26 16:57:09

Cisco路由器ARP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久99精品久久久久久国产越南 | 国产精品免费看 | 日韩在线一区二区 | 欧美成人a| 国产视频91在线 | 农村妇女毛片精品久久久 | 狠狠久| 久久九| 久久久区| 亚洲成人一区二区 | 午夜电影网站 | 色综合视频| 免费看黄视频网站 | 国产精品久久久久久久久久久免费看 | 久久九九99 | 亚洲精品久久久一区二区三区 | 欧美国产精品一区二区 | 神马影院一区二区三区 | 射欧美| 欧美色a v | 欧美一区免费 | www.av7788.com| 国产极品粉嫩美女呻吟在线看人 | 欧美日一区二区 | 91av免费看 | 一级免费毛片 | 精品久久不卡 | 免费观看www| 亚洲天堂中文字幕 | 久久亚洲精品国产精品紫薇 | 国产一区二区在线播放视频 | 91精品国产91久久久久久最新 | 久久国产精品-国产精品 | 日韩一区二 | 99久久久久久99国产精品免 | 狠狠艹| 亚洲成人日韩 | 免费视频一区二区 | 中文字幕成人网 | 久久成人在线视频 | 国产精品久久久久久久久久久久久 |