Python 列表推導式與生成器表達式

Python 列表推導式與生成器表達式

在 Python 中,列表推導式(List Comprehension)和生成器表達式(Generator Expression)是處理序列數據的高效工具。它們不僅能簡化代碼,還能提升數據處理的效率。本文將詳細介紹這兩種表達式的語法、特性、區別及適用場景,并通過豐富的實例幫助你掌握它們的使用技巧。

一、列表推導式:簡潔高效的列表創建

列表推導式是 Python 中創建列表的一種簡潔語法,它將循環、條件判斷等邏輯濃縮成一行代碼,既直觀又高效。

1. 基本語法

?# 基本格式
[表達式 for 變量 in 可迭代對象]# 帶條件判斷的格式
[表達式 for 變量 in 可迭代對象 if 條件]

示例 1:創建簡單列表

?# 傳統方式:使用for循環創建列表
squares = []
for i in range(10):squares.append(i **2)
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# 列表推導式:一行代碼完成
squares = [i** 2 for i in range(10)]
print(squares)  # 結果同上

示例 2:帶條件過濾的列表推導式

?# 篩選偶數的平方
even_squares = [i **2 for i in range(10) if i % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]# 字符串處理:提取單詞首字母大寫
words = ["apple", "banana", "cherry", "date"]
capitalized = [word.capitalize() for word in words if len(word) > 5]
print(capitalized)  # ['Banana', 'Cherry']

2. 嵌套列表推導式

列表推導式支持嵌套,可用于處理二維數據結構(如矩陣):

?# 二維列表(矩陣)
matrix = [[1, 2, 3],[4, 5, 6],[7, 8, 9]
]# 提取矩陣對角線元素
diagonal = [matrix[i][i] for i in range(len(matrix))]
print(diagonal)  # [1, 5, 9]# 矩陣轉置(行變列)
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed)  # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]# 扁平化矩陣(二維轉一維)
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

3. 列表推導式的優勢

  • 簡潔性:將多行循環邏輯壓縮為一行,代碼更緊湊
  • 可讀性:符合 “聲明式編程” 風格,直接表達 “要什么” 而非 “怎么做”
  • 性能:通常比等效的for循環 +append()更快(內部優化)
  • 功能性:結合條件判斷可實現復雜過濾邏輯

4. 常見誤區與最佳實踐

  • 避免過度復雜:嵌套層級不宜過多(建議不超過 2 層),否則可讀性下降

  • ?# 不推薦:過于復雜的嵌套
    complex = [x for x in [y for y in range(20) if y % 2 == 0] if x % 4 == 0]# 推薦:拆分邏輯
    even_numbers = [y for y in range(20) if y % 2 == 0]
    divisible_by_4 = [x for x in even_numbers if x % 4 == 0]

    注意變量泄漏:Python 3 中列表推導式的變量不會泄漏到外部作用域

?x = 10
[x for x in range(5)]
print(x)  # 輸出10(變量x未被修改)

二、生成器表達式:惰性計算的內存優化方案

生成器表達式是一種創建生成器(Generator)的簡潔語法,它與列表推導式類似,但采用惰性計算(Lazy Evaluation)策略,更適合處理大數據集。

1. 基本語法

?# 基本格式(注意使用圓括號)
(表達式 for 變量 in 可迭代對象)# 帶條件判斷的格式
(表達式 for 變量 in 可迭代對象 if 條件)

示例 1:創建生成器

?# 生成器表達式(圓括號可省略,視上下文而定)
squares_gen = (i **2 for i in range(10))
print(squares_gen)  # <generator object <genexpr> at 0x...># 遍歷生成器(每次迭代才計算下一個值)
for num in squares_gen:print(num, end=" ")  # 0 1 4 9 16 25 36 49 64 81

示例 2:與列表推導式的直觀對比

?# 列表推導式:立即生成所有元素并占用內存
list_comp = [i** 2 for i in range(1000000)]
print(type(list_comp))  # <class 'list'>
print(len(list_comp))   # 1000000(已全部生成)# 生成器表達式:僅在迭代時生成元素,內存占用極低
gen_expr = (i **2 for i in range(1000000))
print(type(gen_expr))   # <class 'generator'>
# print(len(gen_expr))  # 報錯:生成器沒有長度(元素未生成)

2. 核心特性:惰性計算

生成器表達式的核心優勢在于惰性計算

  • 元素僅在被請求時(如next()調用或for循環迭代)才會計算
  • 計算后的值不會被存儲,迭代結束后無法重新訪問(一次性使用)
  • 內存占用固定(與數據規模無關),適合處理超大數據集或無限序列
?# 處理無限序列(列表推導式會直接崩潰)
def infinite_numbers():n = 0while True:yield nn += 1# 生成器表達式篩選偶數
even_infinite = (x for x in infinite_numbers() if x % 2 == 0)# 安全獲取前5個偶數(不會耗盡內存)
for _ in range(5):print(next(even_infinite), end=" ")  # 0 2 4 6 8

3. 適用場景

  • 大數據處理:當數據量超過內存限制時,生成器表達式可逐批處理

  • ?# 處理大文件(無需一次性加載全部內容)
    def process_large_file(file_path):with open(file_path, "r") as f:# 生成器表達式逐行處理lines = (line.strip() for line in f)non_empty = (line for line in lines if line)  # 過濾空行for line in non_empty:# 處理邏輯(如數據分析、格式轉換)pass

    鏈式處理:與其他迭代器函數(如mapfilter)配合,實現流式處理

  • ?# 生成器流水線
    numbers = range(100)
    squares = (x** 2 for x in numbers)
    even_squares = (x for x in squares if x % 2 == 0)
    sum_even = sum(even_squares)  # 按需計算,中間結果不存儲

    節省內存:替代列表推導式處理臨時數據(如僅需迭代一次的場景)

?# 計算1到100萬的和(生成器表達式內存占用遠低于列表)
total = sum(i for i in range(1000001))

4. 生成器表達式 vs 列表推導式:關鍵區別

特性列表推導式生成器表達式
語法標識方括號?[]圓括號?()(可省略)
返回類型列表?list生成器?generator
計算方式立即計算所有元素(貪婪計算)按需計算(惰性計算)
內存占用與數據規模成正比固定(極低)
可迭代次數多次(元素已存儲)一次(元素計算后即丟棄)
支持的操作所有列表方法(lenindex等)僅迭代操作(nextfor循環)
適用場景小數據、需多次訪問、隨機訪問大數據、單次迭代、內存受限場景

性能對比實驗

?import memory_profiler
import time@memory_profiler.profile
def list_comprehension():return [i **2 for i in range(10** 7)]  # 1000萬元素@memory_profiler.profile
def generator_expression():return sum(i **2 for i in range(10** 7))  # 同樣1000萬元素# 測試內存占用(列表推導式約占用380MB,生成器表達式約占用0.1MB)
list_comprehension()
generator_expression()# 測試時間(列表推導式耗時更長,因需先創建完整列表)
start = time.time()
list_comprehension()
print(f"列表推導式耗時:{time.time() - start:.2f}s")start = time.time()
generator_expression()
print(f"生成器表達式耗時:{time.time() - start:.2f}s")

三、實戰應用:列表推導式與生成器表達式的協同使用

在實際開發中,兩種表達式并非互斥關系,而是根據場景靈活選擇:

1. 數據轉換與過濾流水線

?# 1. 原始數據(可能很大)
data = range(1, 1000001)  # 1到100萬# 2. 生成器表達式:篩選偶數(惰性計算)
even_numbers = (x for x in data if x % 2 == 0)# 3. 生成器表達式:計算平方(繼續惰性計算)
even_squares = (x **2 for x in even_numbers)# 4. 列表推導式:取前100個結果(轉為列表便于后續復用)
first_100 = [next(even_squares) for _ in range(100)]print(first_100[:5])  # [4, 16, 36, 64, 100]

2. 文本處理場景

?def process_text(file_path):# 生成器表達式:逐行讀取并預處理with open(file_path, "r", encoding="utf-8") as f:lines = (line.strip() for line in f)non_empty = (line for line in lines if line)words = (word.lower() for line in non_empty for word in line.split())# 列表推導式:取前100個單詞(小數據集)sample_words = [next(words) for _ in range(100)]print("樣本單詞:", sample_words[:10])# 生成器表達式:統計詞頻(大數據集)from collections import defaultdictfreq = defaultdict(int)for word in words:freq[word] += 1# 列表推導式:排序并返回前10高頻詞return sorted(freq.items(), key=lambda x: x[1], reverse=True)[:10]

3. 函數參數中的應用

許多內置函數(summaxminanyall等)接受可迭代對象作為參數,此時生成器表達式是更優選擇:

?# 計算1到100的和(生成器表達式更省內存)
total = sum(i for i in range(1, 101))# 檢查是否存在偶數(短路求值,找到第一個即停止)
has_even = any(i % 2 == 0 for i in [1, 3, 5, 7, 8, 9])# 找出最大平方數
max_square = max(x **2 for x in range(1, 10))

四、總結:如何選擇合適的表達式?

1.當滿足以下條件時,優先使用列表推導式

  • 數據規模較小(能完全放入內存)
  • 需要多次迭代或隨機訪問元素
  • 需要使用列表特有的方法(如appendsortreverse
  • 代碼可讀性要求高于內存優化

2.當滿足以下條件時,優先使用生成器表達式

  • 處理大數據集(可能超出內存限制)
  • 只需迭代一次(如求和、過濾后立即處理)
  • 鏈式處理數據(與其他生成器或迭代器配合)
  • 內存資源受限,需要優化內存占用

3.通用原則

  • 從小數據開始,優先保證代碼可讀性
  • 當遇到內存問題或性能瓶頸時,考慮用生成器表達式重構
  • 復雜邏輯優先拆分,避免為了 “一行代碼” 犧牲可讀性

列表推導式和生成器表達式是 Python 中 “寫得少,做得多” 的典型代表。掌握它們不僅能提升代碼效率,更能體現 Pythonic 的編程風格 —— 簡潔、優雅且高效。在實際開發中,靈活運用這兩種工具,將使你的數據處理代碼更上一層樓。

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

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

相關文章

XCF32PVOG48C Xilinx Platform Flash PROM

XCF32PVOG48C 是 Xilinx 公司推出的一款高容量、低功耗的 Platform Flash PROM&#xff08;平臺閃存配置芯片&#xff09;&#xff0c;專為 Xilinx FPGA 和 CPLD 系列產品提供非易失性配置存儲支持。憑借其 32 Mbit 的大容量與出色的系統兼容性&#xff0c;該芯片成為中高端 FP…

重復文件清理工具,附免費鏈接

鏈接:https://pan.baidu.com/s/1s_Zx1eHp5Y-XnbbGldIgvw?pwdkjex 提取碼:kjex 復制這段內容后打開百度網盤手機App&#xff0c;操作更方便哦

【Spring Boot 快速入門】二、請求與響應

目錄請求響應請求Postman 工具簡單參數請求實體參數請求數組集合參數日期參數JSON 參數路徑參數響應請求響應 請求 Postman 工具 Postman 是一款功能強大的網頁調試與發送網頁 HTTP 請求的 Chrome 插件 作用&#xff1a;常用于進行接口測試 簡單參數請求 原始方式 在原始的…

高并發系統技術架構

&#xff08;點個贊&#xff0c;算法會給你推薦更多類似干貨 ~&#xff09; 口訣&#xff1a; CDN 扛靜態&#xff0c;WAF 防惡意&#xff1b;驗證碼攔機器&#xff1b; Nginx 先限流&#xff0c;Sentinel 再熔斷&#xff1b; Redis 扣庫存&#xff0c;MQ 異步寫&#xff1b; 對…

python任意模塊間采用全局字典來實現借用其他類對象的方法函數來完成任務或數據通信的功能

我們在編寫pthon代碼時&#xff0c;模塊間的數據通信主要采用以下幾種方法&#xff1a;1、采用全局變量。所有模塊都通過引用全局變量&#xff0c;通過本模塊對此全局變量數據的修改值&#xff0c;其他模塊也能訪問并得到此全局變量的當前值&#xff0c;由于全局變量的不可控性…

linux 部署 flink 1.15.1 并提交作業

下載 1.15.1 https://flink.apache.org/downloads.html#apache-flink-1151 部署模式分類 會話模式應用模式單作業模式 1、會話模式 先啟動一個集群&#xff0c;保持一個會話&#xff0c;然后通過客戶端提交作業&#xff0c;所有作業都在一個會話執行&#xff1b; 會話模式適合規…

Redis數據量過大的隱患:查詢會變慢嗎?如何避免?

一、Redis數據過多引發的五大隱患&#xff08;附系統交互圖&#xff09; #mermaid-svg-X83bpHUu830QXKUt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-X83bpHUu830QXKUt .error-icon{fill:#552222;}#mermaid-svg-…

網絡與信息安全有哪些崗位:(3)安全運維工程師

安全運維工程師是企業安全防線的 “日常守護者”&#xff0c;既要確保安全設備與系統的穩定運行&#xff0c;又要實時監控潛在威脅&#xff0c;快速響應并處置安全事件&#xff0c;是連接安全技術與業務運營的關鍵角色。其核心價值在于通過常態化運維&#xff0c;將安全風險控制…

魚皮項目簡易版 RPC 框架開發(三)

本文為筆者閱讀魚皮的項目 《簡易版 RPC 框架開發》的筆記&#xff0c;如果有時間可以直接去看原文&#xff0c; 1. 簡易版 RPC 框架開發 前面的內容可以筆者的前面兩個篇筆記 魚皮項目簡易版 RPC 框架開發&#xff08;一&#xff09; 魚皮項目簡易版 RPC 框架開發&#xff08;…

嵌入式Linux:注冊線程清理處理函數

在 Linux 多線程編程中&#xff0c;線程終止時可以執行特定的清理操作&#xff0c;通過注冊線程清理函數&#xff08;thread cleanup handler&#xff09;來實現。這類似于使用 atexit() 注冊進程終止處理函數。線程清理函數用于在線程退出時執行一些資源釋放或清理工作&#x…

【Git】Linux-ubuntu 22.04 初步認識 -> 安裝 -> 基礎操作

文章目錄Git 初識Git 安裝Linux-centosLinux-ubuntuWindowsGit 基本操作配置 Git認識工作區、暫存區、版本庫添加文件 -- 場景一查看 .git 文件添加文件 -- 場景二修改文件版本回退撤銷修改情況一&#xff1a;對于工作區的代碼&#xff0c;還沒有 add情況二&#xff1a;已經 ad…

輕量級音樂元數據編輯器Metadata Remote

簡介 什么是 Metadata Remote (mdrm) &#xff1f; Metadata Remote 是一個基于 Web 的音頻元數據編輯工具&#xff0c;旨在簡化在無頭服務器&#xff08;即沒有圖形用戶界面的服務器&#xff09;上編輯音頻文件的元數據。用戶只需使用 Docker 和瀏覽器&#xff0c;無需復雜的…

免費使用|共享服務器上線RTX3080(20GB顯存)

共享服務器也上架GPU啦 生物信息學中有很多用到GPU的場景&#xff0c;例如我們分享過的&#xff1a;利用GPU加速TensorFlow、部署本地DeepSeek&#xff0c;空間轉錄組學習手冊合輯加速。因此多種GPU供大家選擇&#xff1a;RTX5090、4080S、5070顯卡上機。為了讓此前的CPU服務器…

搭建DM數據守護集群

1環境與規劃準備3個kylin 10操作系統的虛擬機&#xff0c;規劃IP、端口、安裝目錄等。說明搭建REALTIME歸檔模式、事務一致性的數據守護名稱項初始主庫機器dm1初始備庫機器dm2監視器機器dmmon外部業務IP192.168.23.129192.168.23.130192.168.23.131內部心跳IP192.168.23.129192…

AUTOSAR進階圖解==>AUTOSAR_SRS_OCUDriver

AUTOSAR OCU驅動程序詳解 AUTOSAR標準輸出比較單元驅動程序架構與實現分析目錄 1. 概述 1.1 OCU驅動程序簡介1.2 功能概述 2. OCU驅動程序架構 2.1 架構圖2.2 層次結構 3. OCU驅動程序組件設計 3.1 組件圖3.2 接口定義 4. OCU驅動程序狀態管理 4.1 狀態圖4.2 狀態轉換 5. OCU驅…

InfluxDB 與 HTTP 協議交互進階(一)

引言 在當今數字化時代&#xff0c;數據處理的高效性和準確性成為了眾多領域關注的焦點。InfluxDB 作為一款開源的時序數據庫&#xff0c;憑借其高性能、易擴展等特性&#xff0c;在時間序列數據處理中占據了重要地位。而 HTTP 協議作為互聯網應用層的核心協議之一&#xff0c…

NAS遠程訪問新解法:OMV與cpolar的技術協同價值

文章目錄前言1. OMV安裝Cpolar2. 配置FTP公網地址3. OMV FTP 配置4. OMV FTP遠程連接前言 當家庭存儲需求突破本地邊界時&#xff0c;傳統NAS方案往往陷入"連接困境"&#xff1a;復雜的端口轉發配置、高昂的公網IP成本、以及始終存在的安全顧慮…開源解決方案OMV雖然…

vue 渲染 | 不同類型的元素渲染的方式(vue組件/htmlelement/純 html)

省流總結&#xff1a;&#xff08;具體實現見下方&#xff09; vue 組件 ——》<component :is組件名> htmlelement 元素 ——》 ref 、★ v-for ref 或是 ★ vue 的 nextTick 純 html 結構——》v-html 另外&#xff0c;當數據異步加載時&#xff0c;vue3中如何渲…

Charles中文版深度解析,輕松調試API與優化網絡請求

在現代軟件開發過程中&#xff0c;調試API、捕獲HTTP/HTTPS流量以及優化網絡性能是開發者不可避免的挑戰。特別是在處理復雜的網絡請求和驗證API接口的數據傳輸準確性時&#xff0c;開發者需要一款強大且易于使用的工具。Charles抓包工具憑借其功能強大、界面簡潔、易于操作的特…

【CF】Codeforces Round 1039 (Div. 2) E1 (二分答案求中位數)

E1. Submedians (Easy Version)題目&#xff1a;思路&#xff1a;經典不過加了點東西對于求中位數&#xff0c;我們必然要想到二分答案&#xff0c;具體的&#xff0c;對于所有大于等于 x 的數我們令其奉獻為 1&#xff0c;小于的為 -1&#xff0c;如果存在某段區間的奉獻和大于…