2025-08-21 Python進階6——迭代器生成器與with

文章目錄

  • 1 迭代器與生成器
    • 1.1 迭代器
      • 1.1.1 基本使用
      • 1.1.2 手動迭代(帶異常處理)
      • 1.1.3 自定義迭代器
    • 1.2 生成器
      • 1.2.1 工作原理
      • 1.2.2 斐波那契數列示例
    • 1.3 推導式
      • 1.3.1 列表推導式
      • 1.3.2 字典推導式
      • 1.3.3 集合推導式
      • 1.4.4 元組推導式(生成器表達式)
  • 2 with關鍵字
    • 2.1 基本語法
    • 2.2 常用場景
      • 2.2.1 文件操作(最典型)
      • 2.2.2 數據庫連接
      • 2.2.3 線程鎖
    • 2.3 工作原理:上下文管理協議
    • 2.4 自定義上下文管理器
      • 2.4.1 方式 1:類實現
      • 2.4.2 方式 2:使用 contextlib 模塊
    • 2.5 最佳實踐

1 迭代器與生成器

1.1 迭代器

  • 迭代器是可記住遍歷位置的對象
  • 只能向前遍歷,不能后退
  • 核心方法:iter() 創建迭代器,next() 獲取下一個元素

1.1.1 基本使用

# 創建迭代器
list = [1, 2, 3, 4]
it = iter(list)  # 創建迭代器對象# 訪問元素
print(next(it))  # 1
print(next(it))  # 2# 使用for循環遍歷
for x in it:print(x, end=" ")  # 3 4

1.1.2 手動迭代(帶異常處理)

import sysit = iter([1, 2, 3, 4])while True:try:print(next(it))except StopIteration:sys.exit()  # 迭代結束時退出

1.1.3 自定義迭代器

需實現兩個方法:

  • __iter__(): 返回迭代器對象本身
  • __next__(): 返回下一個元素,迭代結束時拋出StopIteration
class MyNumbers:def __iter__(self):self.a = 1return selfdef __next__(self):if self.a <= 20:  # 限制迭代次數x = self.aself.a += 1return xelse:raise StopIteration  # 結束迭代# 使用自定義迭代器
myclass = MyNumbers()
for x in iter(myclass):print(x)  # 輸出1到20

1.2 生成器

  • 使用yield關鍵字的函數稱為生成器
  • 生成器是特殊的迭代器,可逐步產生值
  • 調用生成器函數返回的是迭代器對象

1.2.1 工作原理

  • 執行到yield時返回值并暫停
  • 下次調用時從暫停處繼續執行
  • 適合處理大量數據或無限序列
def countdown(n):while n > 0:yield n  # 返回當前值并暫停n -= 1# 使用生成器
generator = countdown(5)
print(next(generator))  # 5
print(next(generator))  # 4# 用for循環迭代剩余值
for value in generator:print(value)  # 3 2 1

1.2.2 斐波那契數列示例

def fibonacci(n):a, b, counter = 0, 1, 0while True:if counter > n:returnyield a  # 返回當前斐波那契數a, b = b, a + bcounter += 1# 使用生成器
f = fibonacci(10)
for x in f:print(x, end=" ")  # 0 1 1 2 3 5 8 13 21 34 55

1.3 推導式

推導式是一種簡潔的數據處理語法,可從一個序列構建新序列,支持列表、字典、集合和元組。

1.3.1 列表推導式

格式[表達式 for 變量 in 列表 if 條件]

實例 1:過濾并轉換

names = ['Bob','Tom','alice','Jerry','Wendy','Smith']
new_names = [name.upper() for name in names if len(name) > 3]
# 結果: ['ALICE', 'JERRY', 'WENDY', 'SMITH']

實例 2:數值篩選

multiples = [i for i in range(30) if i % 3 == 0]
# 結果: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

1.3.2 字典推導式

格式{key表達式: value表達式 for 變量 in 集合 if 條件}

實例 1:字符串長度字典

listdemo = ['Google','Runoob', 'Taobao']
newdict = {key: len(key) for key in listdemo}
# 結果: {'Google': 6, 'Runoob': 6, 'Taobao': 6}

實例 2:數字平方字典

dic = {x: x**2 for x in (2, 4, 6)}
# 結果: {2: 4, 4: 16, 6: 36}

1.3.3 集合推導式

格式{表達式 for 變量 in 序列 if 條件}

實例 1:計算平方

setnew = {i**2 for i in (1, 2, 3)}
# 結果: {1, 4, 9}

實例 2:字符篩選

a = {x for x in 'abracadabra' if x not in 'abc'}
# 結果: {'d', 'r'}

1.4.4 元組推導式(生成器表達式)

格式(表達式 for 變量 in 序列 if 條件)
注意:返回生成器對象,需用tuple()轉換

實例:生成數字元組

a = (x for x in range(1, 10))  # 生成器對象
print(tuple(a))  # 轉換為元組
# 結果: (1, 2, 3, 4, 5, 6, 7, 8, 9)

2 with關鍵字

with 關鍵字用于上下文管理,簡化資源(如文件、數據庫連接)的獲取與釋放,確保資源使用后被正確清理。

對比傳統資源管理方式:

傳統方式(try-finally)with 語句
需手動調用 close()自動釋放資源
代碼冗長簡潔直觀
易遺漏關閉操作異常安全

傳統文件操作示例

file = open('test.txt', 'r')
try:content = file.read()
finally:file.close()  # 必須手動關閉

2.1 基本語法

with 表達式 [as 變量]:# 代碼塊(使用資源)
  • 表達式返回上下文管理器對象
  • as 變量:可選,將對象賦值給變量
  • 代碼塊執行完畢后,自動觸發資源清理

2.2 常用場景

2.2.1 文件操作(最典型)

# 讀取文件
with open('example.txt', 'r') as file:content = file.read()print(content)
# 退出代碼塊后,文件自動關閉# 同時操作多個文件
with open('in.txt', 'r') as infile, open('out.txt', 'w') as outfile:outfile.write(infile.read().upper())  # 轉換為大寫并寫入

2.2.2 數據庫連接

import sqlite3with sqlite3.connect('mydb.db') as conn:cursor = conn.cursor()cursor.execute('SELECT * FROM users')print(cursor.fetchall())
# 連接自動關閉,無需手動調用 close()

2.2.3 線程鎖

import threadinglock = threading.Lock()with lock:# 臨界區代碼(自動加鎖/解鎖)print("線程安全的操作")

2.3 工作原理:上下文管理協議

支持 with 的對象需實現兩個方法:

  • __enter__():進入上下文時調用,返回值賦給 as 后的變量
  • __exit__():退出上下文時調用,負責資源清理

執行流程

  1. 執行表達式,獲取上下文管理器
  2. 調用 __enter__() 方法,進入上下文
  3. 執行代碼塊
  4. 無論是否發生異常,都調用 __exit__() 方法

異常處理機制

__exit__() 方法接收三個參數:exc_type(異常類型)、exc_val(異常值)、exc_tb(追蹤信息)

  • 返回 True:表示異常已處理,不再傳播
  • 返回 False/None:異常繼續向外傳播

2.4 自定義上下文管理器

2.4.1 方式 1:類實現

class Timer:def __enter__(self):import timeself.start = time.time()return self  # 可通過 as 接收def __exit__(self, exc_type, exc_val, exc_tb):import timeprint(f"耗時: {time.time() - self.start:.2f}秒")return False  # 不抑制異常# 使用
with Timer() as t:sum(range(10000000))  # 執行耗時操作

2.4.2 方式 2:使用 contextlib 模塊

from contextlib import contextmanager@contextmanager
def tag(name):print(f"<{name}>")  # __enter__ 部分yield  # 暫停,執行代碼塊print(f"</{name}>")  # __exit__ 部分# 使用
with tag("h1"):print("這是標題內容")# 輸出:
# <h1>
# 這是標題內容
# </h1>

2.5 最佳實踐

  1. 優先使用 with:處理文件、網絡連接、鎖等資源時,必用 with
  2. 精簡代碼塊with 內只寫與資源相關的操作
  3. 多資源管理:一個 with 可同時管理多個資源(用逗號分隔)
  4. 異常處理:自定義上下文時,明確是否需要抑制異常

with 語句通過自動化資源管理,大幅提升了代碼的可讀性和可靠性,是 Python 中處理資源的首選方式。

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

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

相關文章

C++——C++重點知識點復習2(詳細復習模板,繼承)

目錄 模板 函數模板 類模板 非類型模板參數 模板的特化 函數模板特化 類模板的特化 為什么普通函數可以分離&#xff1f; 繼承 繼承概念 基類和派生類對象賦值轉換&#xff08;切割&#xff0c;切片&#xff09; 隱藏 派生類的默認成員函數 .復雜的菱形繼承及菱形…

python 項目編號 2025821 有關于中英文數據的收集、處理

python專欄記錄&#xff1a;前言 批量讀取單詞 JSON 文件 → 解析出單詞、釋義、例句、短語 → 數據清洗&#xff08;去掉特殊符號&#xff09; → 同步更新到 MySQL 數據庫。 內容 import json import pymysql import re import time from pymysql.converters import escape_s…

Document Solutions .NET Bundle 8.2.0

Document Solutions .NET Bundle 8.2.0MESCIUS 的 Document Solutions .NET Bundle 是一套完整的 API 和查看工具&#xff0c;可增強文檔處理并提高效率。它包含 Excel、Word、PDF 和圖像文檔&#xff0c;以及 PDF 查看器、數據查看器和圖像查看器的標準許可證。它將強大的 .NE…

在職老D滲透日記day20:sqli-labs靶場通關(第27關)get報錯注入 過濾select和union ‘閉合

5.27.第27關 get報錯注入 過濾select和union 閉合function blacklist($id) { $id preg_replace(/[\/\*]/,"", $id); //strip out /* $id preg_replace(/[--]/,"", $id); //Strip out --. $id preg_replace(/[#]/,"", $id); //Strip out #. $…

Go 并發編程-channel

channel 文章目錄channel簡介基本概念類型表示法值表示法操作的特性初始化通道接收元素值Happens before發送值例1核心組件關鍵執行順序輸出示例&#xff08;可能順序&#xff09;設計要點例2例3關閉通道長度與容量單向通道主要用途增強代碼表達性和安全性&#xff08;最重要的…

開源和免費一樣嗎?以商城系統為例為您分析~

開源和免費并不完全一樣&#xff0c;二者在核心定義、權利范圍和實際應用中存在顯著區別&#xff0c;具體可以從以下幾個方面理解&#xff1a; 1. 核心定義不同開源&#xff08;Open Source&#xff09;&#xff1a; 指軟件的源代碼是公開可獲取的&#xff0c;任何人都可以查看…

CMOS知識點 MOS管飽和區電流公式

知識點16&#xff1a;同上篇一樣&#xff0c;MOS管主要有3個工作區域&#xff1a;截止區&#xff08;Cut-off Region&#xff09;&#xff1a; < &#xff0c;沒有溝道形成&#xff0c;幾乎沒有電流。線性區/三極管區&#xff08;Triode Region&#xff09;&#xff1a; &g…

【集合框架LinkedList底層添加元素機制】

在 Java 集合框架中&#xff0c;LinkedList 與 ArrayList 是兩種截然不同的線性表實現。如果說 ArrayList 像一個可以伸縮的“盒子陣列”&#xff0c;那么 LinkedList 就像一條由“節點”串聯而成的“雙向鏈條”。今天&#xff0c;我們將深入 LinkedList 的源碼&#xff0c;一步…

《P2700 逐個擊破》

題目背景三大戰役的平津戰場上&#xff0c;傅作義集團在以北平、天津為中心&#xff0c;東起唐山西至張家口的鐵路線上擺起了一字長蛇陣&#xff0c;并企圖在潰敗時從海上南逃或向西逃竄。為了就地殲敵不讓其逃走&#xff0c;指揮官制定了先切斷敵人東西兩頭退路然后再逐個殲滅…

C6.0:晶體管放大器的原理與應用(基極偏置篇)

將晶體管Q點偏置在負載線中點附近后&#xff0c;如果將一個小的交流信號耦合到基極上&#xff0c;便會產生一個交流的集電極電壓&#xff0c;交流集電極電壓與交流基極電壓波形相似&#xff0c;但是幅度要大了很多&#xff0c;即交流集電極電壓是對交流基極電壓的放大。本篇學習…

Oracle: cannot decrease column length because some value is too big

1.背景今天項目上查不到數據,查庫發現默認20位的字段被改為了200,用的還是char類型&#xff0c;填充了一堆空格 2.知識LENGTH() 函數用于計算字符串字段 長度TRIM() 函數用于去除字符串字段 column 前后的空格&#xff08;默認&#xff09;或指定字符&#xff1a;SUBSTR() 用于…

Elasticsearch 寫入全鏈路:從單機到集群

0. 先把術語擺正 Index&#xff08;索引&#xff09;&#xff1a;邏輯數據集合&#xff0c;≈ MySQL 的庫。Document&#xff08;文檔&#xff09;&#xff1a;一條 JSON 數據&#xff0c;≈ MySQL 的行。Field&#xff08;字段&#xff09;&#xff1a;文檔里的鍵值&#xff0…

Java多線程編程——基礎篇

目錄 前言 一、進程與線程 1、進程 2、線程 二、并發與并行 1、并發 2、并行 三、線程調度 1、CPU時間片 2、調度方式 ①時間片輪轉 ②搶占式調度 四、線程實現方式 1、繼承 Thread 類 Thread的多種構造函數&#xff1a; 2、實現 Runnable 接口 五、線程的核心方法 1、start() …

阿里云的centos8 服務器安裝MySQL 8.0

在 CentOS 8 上安裝 MySQL 8.0 可以通過添加 MySQL 官方 YUM 倉庫并使用 dnf 命令安裝。以下是具體步驟&#xff1a; 步驟如下&#xff1a; 下載并添加 MySQL 官方 YUM 倉庫 運行以下命令下載 MySQL 8.0 的 YUM 倉庫配置文件&#xff1a; sudo dnf install https://dev.mysql.…

【運維進階】Linux 正則表達式

Linux 正則表達式定義&#xff1a;正則表達式是一種pattern&#xff08;模式&#xff09;&#xff0c;用于與待搜索字符串匹配&#xff0c;以查找一個或多個目標字符串。組成&#xff1a;自成體系&#xff0c;由兩類字符構成普通字符&#xff1a;未被顯式指定為元字符的所有可打…

STM32輸入捕獲相位差測量技術詳解(基于TIM1復位模式)

本文將深入解析基于STM32定時器輸入捕獲功能的方波相位差測量技術&#xff0c;通過復位模式實現高精度相位檢測。以下是完整的代碼實現與詳細原理分析。一、相位差測量原理相位差測量基于兩個同頻方波信號下降沿時間差計算。核心原理&#xff1a;?復位模式?&#xff1a;將TIM…

什么是股指期貨可轉移阿爾法策略?

阿爾法&#xff08;Alpha&#xff09;是投資領域的一個術語&#xff0c;用來衡量投資組合的超額收益。簡單來說&#xff0c;阿爾法就是你在市場上賺的比平均水平多出來的那部分錢。比如&#xff0c;市場平均收益率是5%&#xff0c;但你的投資組合收益率是10%&#xff0c;那你的…

AXI GPIO S——ZYNQ學習筆記10

AXI GPIO 同意通道混合輸入輸出中斷控制#KEY set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[0]}] set_property PACKAGE_PIN J13 [get_ports {AXI_GPIO_KEY_tri_io[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[1]}] set_pro…

如何通過傳感器選型優化,為設備壽命 “續航”?

在當今競爭激烈的工業領域&#xff0c;企業就像在一場沒有硝煙的戰爭中角逐&#xff0c;設備便是企業的“秘密武器”。設備的使用壽命&#xff0c;如同武器的耐用程度&#xff0c;直接決定了企業在生產戰場上的“戰斗力”。延長設備壽命&#xff0c;已然成為眾多企業降低生產成…

WebSocket連接的例子

// 初始化WebSocket連接 const initWebSocket () > {console.log("初始化鏈接中...")const websocketUrl ws://61.54.84.16:9090/;// WebSocket服務器地址websocket new WebSocket(websocketUrl)//使用真實的webscket// websocket new MockWebSocket(websocket…