python中的生成器

概要

python中的生成器是一種特殊的迭代器,如果按照c語言的說法,就是一種特殊的指針,但是python語言的一個語言特性是兼容了函數化編程,類似lambda匿名函數機制。

本文重點介紹生成器表達式的使用,是一種很快捷,節約內存的寫法。

生成器(Generator)是一種特殊的迭代器,它能讓你用一種非常高效的方式遍歷序列。它的核心思想是:按需生成數據,而不是一次性創建所有數據。

想象一下你有一百萬個數字要處理。如果你把它們全部加載到內存中,可能會導致程序變慢甚至崩潰。生成器就像一個“懶惰”的工廠,它只在你需要下一個數字時,才生產并提供給你,用完就丟棄,因此它能大大節省內存。

生成器和普通函數的區別

生成器看起來像一個普通的函數,但它最大的不同是使用 yield 關鍵字而不是 return

  • return:當你調用一個普通函數時,它會執行到 return 語句,然后返回一個值,并徹底結束。下次再調用這個函數時,它會從頭開始執行。

  • yield:當你調用一個生成器函數時,它會執行到 yield 語句,然后返回一個值并暫停。它的狀態(包括所有局部變量和執行位置)會被保存下來。下次你再次要求它提供值時,它會從上次暫停的地方繼續執行,直到遇到下一個 yield

怎么創建生成器?

有兩種主要方式創建生成器:

1. 生成器函數

這是最常見的方式,和定義普通函數一樣,只是將 return 換成 yield

def simple_generator():yield 1yield 2yield 3# 調用生成器函數,會返回一個生成器對象
gen = simple_generator()# 每次調用 next(),它都會繼續執行到下一個 yield
print(next(gen))  # 輸出: 1
print(next(gen))  # 輸出: 2
print(next(gen))  # 輸出: 3# 當沒有更多的 yield 語句時,會引發 StopIteration 異常
# print(next(gen))  # 這行會報錯

通常,我們會用 for 循環來遍歷生成器,因為 for 循環會自動處理 StopIteration 異常。

for item in simple_generator():print(item)
# 輸出:
# 1
# 2
# 3
2. 生成器表達式

偽代碼演示:

(你想生成什么 for 你要迭代什么 in 哪個序列 if 你的條件)

這是一種更簡潔的寫法,類似于列表推導式,但用圓括號 () 而不是方括號 []

  • 列表推導式(List Comprehension):一次性生成所有數據,并存入列表。

squares_list = [x*x for x in range(10)]
print(squares_list) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 生成器表達式(Generator Expression):按需生成數據,返回一個生成器對象。

squares_gen = (x*x for x in range(10))
print(squares_gen) # <generator object <genexpr> at ...># 只有當你遍歷它時,數據才會被生成
for item in squares_gen:print(item)

生成器與列表的區別

從整體來看,區別最大的就是生成器的內存占用是很小的,下面看一個例子:

列表 (List) 的內存消耗

當你使用列表推導式或手動構建一個列表時,Python 會立即分配足夠的內存來存儲所有的元素。

例如:

all_squares = [x*x for x in range(1, 1000001)]

要執行這行代碼,Python 會一次性計算 100 萬個數字的平方,并將它們全部存儲在一個列表中。如果每個整數占用 4 字節,那么這個列表至少需要 1,000,000 * 4 = 4 MB 的內存,再加上列表本身的一些開銷。

這個過程是立即的、一次性的。這很方便,但如果數據量非常大,它可能會耗盡你的系統內存,導致程序崩潰或運行緩慢。

生成器 (Generator) 的內存消耗

與列表不同,生成器是惰性求值的。它不會一次性計算并存儲所有元素。它只在需要時才計算下一個值。

例如:

all_squares_gen = (x*x for x in range(1, 1000001))

當你執行這行代碼時,Python 并沒有做任何計算。它只是創建了一個生成器對象。這個對象只存儲了如何計算下一個值的指令(即 x*x)以及當前的狀態(即 x 的值)。

當你開始迭代這個生成器時,比如在一個 for 循環中,它會一個接一個地生成值,并且只在內存中保留當前正在使用的那個值

類型工作原理內存使用
列表一次性創建并存儲所有元素。消耗大量內存,與元素數量成正比。
生成器逐個按需生成元素。消耗極少內存,與元素數量無關。

生成器有這樣的優點,歸功于python這樣高級語言的自動垃圾回收機制

生成器:即時分配,即時銷毀

當生成器在 for 循環中被調用時,它會:

  1. 計算下一個值。

  2. 返回這個值。

  3. 立即釋放與這個值相關的內存。

上面的例子里,生成器每計算一次,就會把上一次的計算好的數據刪除回收,節約了空間。

生成器具體應用例子

下面是兩端程序,實現的內容是一樣的,但是第一個使用一般的函數定義寫的,第二個是用匿名函數lambda和生成器寫的,比較兩者的區別

def count_fives(n):"""Return the number of values i from 1 to n (including n)where sum_digits(n * i) is 5.>>> count_fives(10)  # Among 10, 20, 30, ..., 100, only 50 (10 * 5) has digit sum 51>>> count_fives(50)  # 50 (50 * 1), 500 (50 * 10), 1400 (50 * 28), 2300 (50 * 46)4"""i = 1count = 0while i <= n:if sum_digits(n * i) == 5:count += 1i += 1return countdef count_primes(n):"""Return the number of prime numbers up to and including n.>>> count_primes(6)   # 2, 3, 53>>> count_primes(13)  # 2, 3, 5, 7, 11, 136"""i = 1count = 0while i <= n:if is_prime(i):count += 1i += 1return count

第二段

def sum_digits(y):"""Return the sum of the digits of non-negative integer y."""total = 0while y > 0:total, y = total + y % 10, y // 10return totaldef is_prime(n):"""Return whether positive integer n is prime."""if n == 1:return Falsek = 2while k < n:if n % k == 0:return Falsek += 1return Truedef count_cond(condition):"""Returns a function with one parameter N that counts all the numbers from1 to N that satisfy the two-argument predicate function Condition, wherethe first argument for Condition is N and the second argument is thenumber from 1 to N.>>> count_fives = count_cond(lambda n, i: sum_digits(n * i) == 5)>>> count_fives(10)   # 50 (10 * 5)1>>> count_fives(50)   # 50 (50 * 1), 500 (50 * 10), 1400 (50 * 28), 2300 (50 * 46)4>>> is_i_prime = lambda n, i: is_prime(i) # need to pass 2-argument function into count_cond>>> count_primes = count_cond(is_i_prime)>>> count_primes(2)    # 21>>> count_primes(3)    # 2, 32>>> count_primes(4)    # 2, 32>>> count_primes(5)    # 2, 3, 53>>> count_primes(20)   # 2, 3, 5, 7, 11, 13, 17, 198""""*** YOUR CODE HERE ***"return lambda n: sum(1 for i in range(1,n+1) if condition(n,i))

套用生成器表達式:

(你想生成什么 for 你要迭代什么 in 哪個序列 if 你的條件)

這個代碼意味著遍歷1到n的序列,如果條件滿足condition,則生成1,而外部的sum()函數就會把1加起來,實現計數。

一行就解決了這個問題,函數式編程的泛用性可見一斑

為什么使用生成器?

  1. 節省內存:這是最大的優勢。它不會一次性把所有數據都存到內存里,特別適合處理大數據集。

  2. 延遲計算:數據只在需要時才被生成,這對于某些計算密集型任務非常有用。

  3. 可讀性高:生成器函數比編寫一個自定義迭代器類要簡單得多。

總結

  • 生成器是按需生成數據的迭代器。

  • yield 關鍵字創建生成器函數

  • 用圓括號 () 創建生成器表達式

  • 它們的主要優點是內存高效延遲計算

如果你需要處理大量數據或者進行無限序列的操作,生成器是 Python 中一個非常有用的工具。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94016.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94016.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94016.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Coze】Windows 環境下使用 Docker 部署 Coze Studio 的詳細指南

一、前言&#xff1a; Coze Studio 是一站式 AI Agent 開發工具。提供各類最新大模型和工具、多種開發模式和框架&#xff0c;從開發到部署&#xff0c;為你提供最便捷的 AI Agent 開發環境。 提供 AI Agent 開發所需的全部核心技術&#xff1a;Prompt、RAG、Plugin、Workflo…

票務系統小程序源碼

1. 系統概述 github地址 本系統是一個歷經多年迭代和市場檢驗的綜合性智慧票務解決方案。它以小程序和后臺管理系統為核心&#xff0c;深度整合了線上OTA渠道、線下多種支付方式以及各類智能硬件&#xff0c;為旅游景區、展館、活動中心等場景提供穩定、高效、功能完備的一體化…

Python 文件操作與異常處理全解析

目錄 一、文件的基本概念 1. 什么是文件 2. 文件操作的核心內容 3. 文件操作的作用 二、文件的基本操作 1. 文件操作三步走 2. 打開文件&#xff1a;open () 函數 2.1 文件路徑 2.2 常用 mode 模式 3. 寫入文件&#xff1a;write () 函數 4. 關閉文件&#xff1a;cl…

領碼方案:通用物聯網數據采集低代碼集成平臺——萬物智聯時代的黃金鑰匙

摘要&#xff1a; 領碼方案通過“協議抽象層低代碼引擎AI智能中樞”架構&#xff0c;實現物聯網設備數據采集、存儲、分析的零代碼配置化集成。支持200工業協議即插即用&#xff0c;10分鐘完成設備上云&#xff0c;數據流轉效率提升70%&#xff0c;AI模型調用耗時降低90%。該方…

后臺管理系統-10-vue3之用戶管理組件配置子路由和靜態頁面

文章目錄 1 配置子路由 1.1 router/index.js(添加路由) 1.2 views/User.vue(用戶管理) 1.3 驗證路由是否生效 2 User.vue(靜態頁面) 2.1 搜索框和表格的靜態搭建 2.2 用戶表格的數據獲取渲染 2.2.1 user.js(準備數據) 2.2.2 mock.js(攔截請求的URL) 2.2.3 api.js(axios請求的UR…

AMPAK正基科技系列產品有哪些廣泛應用于IOT物聯網

關於正基AMPAK 智慧物聯網 無線射頻模組專家 專業品牌 正基科技是一家擁有超過 20 年無線模組研發、設計、生產、行銷與產品技術整合服務經驗的公司。 有專業的高頻模組硬體設計及軟體整合工程師團隊&#xff0c;具備豐富的客戶應用經驗&#xff0c;能因應客戶與市場導向的產品…

【PyTorch】環境配置

文章目錄1. 配置cuda環境2. 配置conda環境3. 配置pytorch gpu環境1. 配置cuda環境 在命令行輸入以下命令可以查看當前顯卡驅動版本和最高支持的cuda版本 nvidia-smi根據cuda版本去官網下載并安裝cuda 下載鏈接&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive…

vue3實現實現手機/PC端錄音:recorder-core

通過 recorder-core 這個插件實現錄音recorder-core插件使用下方的js文件是安裝后封裝的一個js文件&#xff0c;在需要使用的地方直接引入這個文件&#xff1a;import record from “./recorderCore.js”;// 文件名稱&#xff1a;recorderCore.js// recorder-core插件使用方式…

deepseek 本地部署,如何支持工具調用

這里需要考慮顯卡是否和模型匹配&#xff0c;支不支持推理 先把模版拉取到本地&#xff1a;git clone https://github.com/sgl-project/sglang.git 我的位置是 /data/home/sglang 注意模版位于sglang下的examples/chat_template中 根據對應的模版部署模型&#xff0c;比如 …

Excel中運行VB的函數

“插入” -》 “模塊”Function FormatCodeFlex(inputStr As String, Optional defaultVal As String "0") As StringOn Error GoTo ErrorHandlerDim parts() As StringDim i As Integer 使用 "-" 分割字符串parts Split(inputStr, "-") 確保至…

《零基礎入門AI:深度學習之NLP基礎學習》

一、自然語言處理&#xff08;NLP&#xff09;概述 1. 基本概念 ? 自然語言處理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能與計算語言學交叉的核心領域&#xff0c;致力于實現計算機對人類自然語言的自動理解、分析、生成與交互。其研究目標在于構…

保姆級Debezium抽取SQL Server同步kafka

前言&#xff1a; Debezium SQL Server連接器捕獲SQL Server數據庫模式中發生的行級更改。 官方2.0文檔&#xff1a; Debezium connector for SQL Server :: Debezium Documentation 有關與此連接器兼容的SQL Server版本的信息&#xff0c;請參閱 SQL Server Database: 201…

鴻蒙安卓前端中加載丟幀:ArkWeb分析

序章&#xff1a;卡頓的數字世界 在每秒60幀的視覺交響樂中&#xff0c;每一幀都是精心編排的節拍。當這些節拍開始丟失——就像交響樂中突然靜音的提琴部——我們便遭遇了加載丟幀的數字噩夢。這不是簡單的性能下降&#xff0c;而是一場渲染管線的全面崩潰&#xff0c;是數字…

Spring Cloud Netflix學習筆記06-Zuul

文章目錄概述什么是Zuul?Zuul 能干嘛&#xff1f;Zuul入門案例pom依賴application.yml啟動類隱藏真實路徑概述 什么是Zuul? Zuul包含了對請求的路由(用來跳轉的)和過濾兩個最主要功能&#xff1a; 其中路由功能負責將外部請求轉發到具體的微服務實例上&#xff0c;是實現外…

c# 和 c++ 怎樣結合

c# 和 c 怎樣結合在軟件開發中&#xff0c;C# 和 C 通常用于不同的場景和目的&#xff0c;但有時需要將它們結合使用以充分利用兩種語言的優點。以下是幾種常見的方法來實現 C# 和 C 的結合&#xff1a;1. P/Invoke&#xff08;Platform Invocation Services&#xff09;P/Invo…

開源分布式數據庫(Dgraph)

Dgraph 是一款專為處理復雜關系數據設計的開源分布式圖數據庫&#xff0c;核心目標是提供高性能、高可擴展性的圖數據存儲與查詢能力。其設計融合了原生圖模型與分布式架構&#xff0c;支持 GraphQL 查詢語言&#xff0c;適用于社交網絡、知識圖譜、推薦系統等場景。 一、技術架…

Apache ShenYu和Nacos之間的通信原理

這是一個非常經典的服務注冊發現和動態配置管理的案例。ShenYu 作為網關,需要實時感知后端微服務的上線、下線以及其元數據信息(如 API 接口列表)的變化,同時它自身的配置也可能需要動態調整。Nacos 則作為注冊中心和配置中心,扮演了“服務電話簿”和“動態配置倉庫”的角…

強制重啟導致Ubuntu24.04LTS amd的WIFI無法使用的解決方案

強制重啟導致Ubuntu24.04LTS amd的WIFI無法使用的解決方案 前言 ? 我按下了<ctrl><alt><prtsc>組合鍵&#xff0c;然后按住<ctrl><alt>不放&#xff0c;讓我的死機的圖形化的Ubuntu強制重啟&#xff0c;然后再次打開發現&#xff0c;我的ubu…

Java基礎面試題02

引用&#xff1a;&#xff08;代碼隨想錄的八股轉免費了&#xff09;以下為網址 卡碼筆記 本文為學習以上文章的筆記&#xff0c;如果有時間推薦直接去原網址 Java中的數據類型有哪些&#xff1f;分為哪兩大類&#xff1f; (考點&#xff1a;Java數據類型及其分類) 【簡單】 基…

RabbitMQ:SpringAMQP Fanout Exchange(扇型交換機)

目錄一、案例需求二、基礎配置三、代碼實現扇形交換機也叫做廣播交換機&#xff0c;通過交換機將消息發送給所有的隊列。 生產者源碼 消費者源碼 一、案例需求 在RabbitMQ控制臺中&#xff0c;聲明隊列fanout.queue1和fanout.queue2。在RabbitMQ控制臺中&#xff0c;聲明交換…