python 中的生成器

image.png

目錄

  • 生成器示例
      • 基本生成器示例
      • 無限序列生成器
      • 使用生成器表達式
      • 實用示例:按行讀取大文件
      • 生成器的 `send`、`throw` 和 `close` 方法
  • 生成器和迭代器
      • 迭代器(Iterator)
        • 定義
        • 創建
        • 使用
        • 示例
      • 生成器(Generator)
        • 定義
        • 創建
        • 使用
        • 示例
      • 主要區別和聯系
        • 1. 創建方式
        • 2. 代碼簡潔性
        • 3. 內存效率
        • 4. 使用方式
      • 示例對比
        • 迭代器示例
        • 生成器示例
      • 總結
  • 生成器和列表
      • 1. 定義和存儲
      • 2. 內存使用
      • 3. 訪問方式
      • 4. 惰性求值(Lazy Evaluation)
      • 5. 可復用性
      • 6. 示例對比
        • 序列示例
        • 生成器示例
      • 總結
  • 生成器的應用總結

在 Python 中,生成器(Generator)是一種特殊類型的迭代器,允許你在迭代過程中逐步生成值,而不是一次性生成所有值。生成器的創建通常通過包含 yield 關鍵字的函數實現。當函數包含 yield 時,該函數會返回一個生成器對象。
image.png

生成器的主要優點包括:

  1. 延遲求值(Lazy Evaluation):生成器在需要值的時候才生成值,這樣可以節省內存。
  2. 流式處理(Stream Processing):適用于處理大型數據集或無限序列,因為它們不會將所有值一次性加載到內存中。
  3. 簡潔的代碼:生成器可以使代碼更簡潔和可讀,特別是處理復雜迭代邏輯時。
    image.png

生成器示例

下面是一些使用生成器的示例:

image.png

基本生成器示例

一個簡單的生成器函數,它生成從 0 到 n 的數字:

def simple_generator(n):for i in range(n):yield igen = simple_generator(5)
for value in gen:print(value)

輸出:

0
1
2
3
4

無限序列生成器

生成器可以用于創建無限序列,例如生成斐波那契數列:

def fibonacci():a, b = 0, 1while True:yield aa, b = b, a + bfib_gen = fibonacci()
for _ in range(10):print(next(fib_gen))

輸出:

0
1
1
2
3
5
8
13
21
34

使用生成器表達式

生成器表達式是生成器的簡潔形式,類似于列表解析(List Comprehensions),但它們使用圓括號 () 而不是方括號 []。例如:

gen_exp = (x * x for x in range(10))
for value in gen_exp:print(value)

輸出:

0
1
4
9
16
25
36
49
64
81

實用示例:按行讀取大文件

生成器可以用于按行讀取大文件而不占用過多內存:

def read_large_file(file_path):with open(file_path, 'r') as file:while line := file.readline():yield line.strip()file_gen = read_large_file('large_file.txt')
for line in file_gen:print(line)

生成器的 sendthrowclose 方法

image.png

生成器對象有三個額外的方法:

  • send(value):恢復生成器,并向生成器提供一個值,該值會成為生成器中 yield 表達式的返回值。
  • throw(type, value=None, traceback=None):在生成器中拋出一個異常。
  • close():停止生成器。

示例:

def generator_with_send():while True:value = (yield)print(f'Received: {value}')gen = generator_with_send()
next(gen)  # 預激生成器
gen.send('Hello')
gen.send('World')
gen.close()

輸出:

Received: Hello
Received: World

使用生成器可以編寫高效、易讀的代碼,特別是在處理需要逐步生成數據的場景時。

生成器和迭代器

image.png

生成器和迭代器在 Python 中都是用于迭代的對象,但它們之間有一些顯著的區別和聯系。下面是生成器和迭代器的詳細比較:

迭代器(Iterator)

定義
  • 迭代器是一個實現了 __iter__()__next__() 方法的對象。
  • 任何實現了這些方法的對象都可以用于迭代。
創建
  • 迭代器通常通過實現這兩個方法來創建。
  • 也可以使用內置的 iter() 函數從一個可迭代對象(如列表或元組)創建迭代器。
使用
  • 通過 next() 函數獲取下一個元素。
  • 當沒有更多元素時,next() 會拋出 StopIteration 異常。
示例
# 創建一個迭代器
class MyIterator:def __init__(self, start, end):self.current = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.current >= self.end:raise StopIterationelse:self.current += 1return self.current - 1it = MyIterator(1, 5)
for num in it:print(num)# 使用內置的 iter() 函數
lst = [1, 2, 3, 4]
it = iter(lst)
print(next(it))  # 輸出: 1
print(next(it))  # 輸出: 2

生成器(Generator)

定義
  • 生成器是一個特殊的迭代器,通過函數來定義,使用 yield 關鍵字生成值。
  • 每次調用生成器函數時,生成器函數返回一個生成器對象,這個對象實現了迭代器協議。
創建
  • 通過包含 yield 關鍵字的函數創建。
  • 生成器表達式也可以用于創建生成器,類似于列表解析(List Comprehensions)。
使用
  • 通過 next() 函數獲取下一個元素,或在 for 循環中使用。
  • 當沒有更多元素時,生成器自動拋出 StopIteration 異常。
示例
# 生成器函數
def my_generator():for i in range(1, 5):yield igen = my_generator()
for num in gen:print(num)# 生成器表達式
gen_exp = (x * x for x in range(5))
for num in gen_exp:print(num)

主要區別和聯系

1. 創建方式
  • 迭代器:通過實現 __iter__()__next__() 方法的類創建。
  • 生成器:通過函數定義,使用 yield 關鍵字。
2. 代碼簡潔性
  • 迭代器:創建迭代器需要定義一個類并實現兩個方法。
  • 生成器:生成器函數更簡潔,只需定義一個函數并使用 yield
3. 內存效率
  • 迭代器:通常用于較小的數據集合,因為它們需要預先定義數據集合。
  • 生成器:適用于大數據集合或無限數據流,因為它們是按需生成數據。
4. 使用方式
  • 迭代器:需要顯式調用 next() 獲取下一個元素。
  • 生成器:可以像普通函數一樣調用,并在 for 循環中直接使用。

示例對比

迭代器示例
class Counter:def __init__(self, low, high):self.current = lowself.high = highdef __iter__(self):return selfdef __next__(self):if self.current > self.high:raise StopIterationelse:self.current += 1return self.current - 1counter = Counter(1, 5)
for num in counter:print(num)
生成器示例
def counter(low, high):current = lowwhile current <= high:yield currentcurrent += 1for num in counter(1, 5):print(num)

總結

  • 生成器是迭代器的一種,提供了更簡潔的語法和更高的內存效率,適合處理大數據或無限序列。
  • 迭代器提供了更靈活的實現方式,適合需要自定義迭代行為的場景。

生成器和列表

image.png

生成器和序列在 Python 中有顯著的區別。下面從幾個方面來詳細比較它們:

1. 定義和存儲

  • 序列(Sequence)

    • 序列是一種容器數據類型,包含了一系列有序的元素,如列表(list)、元組(tuple)、字符串(string)等。
    • 序列中的元素是預先存儲在內存中的,可以通過索引直接訪問。
  • 生成器(Generator)

    • 生成器是一種特殊的迭代器,用于逐步生成元素。生成器函數使用 yield 關鍵字來返回一個生成器對象。
    • 生成器在運行時逐步生成元素,并不會將所有元素一次性存儲在內存中。

2. 內存使用

  • 序列:由于序列會將所有元素存儲在內存中,所以在處理大數據集時可能會占用大量內存。
  • 生成器:生成器按需生成元素,僅在需要時生成下一個元素,因而在處理大數據集時非常節省內存。

3. 訪問方式

  • 序列:支持通過索引訪問元素,并且支持切片操作。例如 lst[0]lst[1:3]
  • 生成器:不支持索引訪問和切片操作。只能通過迭代器接口(如 for 循環或 next() 函數)逐個獲取元素。

4. 惰性求值(Lazy Evaluation)

  • 序列:所有元素在創建時就被立即計算并存儲。
  • 生成器:元素是按需計算的,只有在訪問時才會生成對應的值。這種惰性求值方式可以提高效率,尤其在處理潛在的無限序列或大數據集時。

5. 可復用性

  • 序列:可以多次遍歷。例如,你可以多次使用 for 循環遍歷列表。
  • 生成器:只能遍歷一次。一旦生成器到達末尾,再次遍歷時需要重新創建生成器對象。

6. 示例對比

序列示例
# 使用列表(序列)
sequence = [1, 2, 3, 4, 5]
for item in sequence:print(item)# 可以通過索引訪問
print(sequence[2])# 可以多次遍歷
for item in sequence:print(item)
生成器示例
# 使用生成器
def simple_generator():for i in range(1, 6):yield igen = simple_generator()# 逐個獲取生成器的值
for item in gen:print(item)# 再次遍歷需要重新創建生成器
gen = simple_generator()
for item in gen:print(item)# 不能通過索引訪問
try:print(gen[2])
except TypeError as e:print(e)  # 'generator' object is not subscriptable

總結

  • 序列適用于需要頻繁隨機訪問元素和多次遍歷的場景。
  • 生成器適用于處理大型數據集或無限序列,以及按需生成數據的場景。生成器在內存效率和惰性求值方面有顯著優勢。

生成器的應用總結

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

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

相關文章

【python學習】自定義函數的一些高級用法-2

8. 生成器函數 生成器函數允許你定義一個可以“記住”其當前執行狀態的函數&#xff0c;并在下次調用時從上次離開的位置繼續執行。生成器函數使用yield關鍵字而不是return。 def simple_generator(): yield 1 yield 2 yield 3 gen simple_generator() print(next(gen)) # …

隱私計算實訓營第二期第十課:基于SPU機器學習建模實踐

隱私計算實訓營第二期-第十課 第十課&#xff1a;基于SPU機器學習建模實踐1 隱私保護機器學習背景1.1 機器學習中隱私保護的需求1.2 PPML提供的技術解決方案 2 SPU架構2.1 SPU前端2.2 SPU編譯器2.3 SPU運行時2.4 SPU目標 3 密態訓練與推理3.1 四個基本問題3.2 解決數據來源問題…

全新升級!中央集中式架構功能測試為新車型保駕護航

“軟件定義汽車”新時代下&#xff0c;整車電氣電氣架構向中央-區域集中式發展已成為行業共識&#xff0c;車型架構的變革帶來更復雜的整車功能定義、更多的新技術的應用&#xff08;如SOA服務化、智能配電等&#xff09;和更短的車型研發周期&#xff0c;對整車和新產品研發的…

OkHttp的源碼解讀1

介紹 OkHttp 是 Square 公司開源的一款高效的 HTTP 客戶端&#xff0c;用于與服務器進行 HTTP 請求和響應。它具有高效的連接池、透明的 GZIP 壓縮和響應緩存等功能&#xff0c;是 Android 開發中廣泛使用的網絡庫。 本文將詳細解讀 OkHttp 的源碼&#xff0c;包括其主要組件…

Qt實現手動切換多種布局

引言 之前寫了一個手動切換多個布局的程序&#xff0c;下面來記錄一下。 程序運行效果如下&#xff1a; 示例 需求 通過點擊程序界面上不同的布局按鈕&#xff0c;使主工作區呈現出不同的頁面布局&#xff0c;多個布局之間可以通過點擊不同布局按鈕切換。支持的最多的窗口…

如何使用 AppML

如何使用 AppML AppML(Application Markup Language)是一種輕量級的標記語言,旨在簡化Web應用的創建和部署過程。它允許開發者通過XML或JSON格式的配置文件來定義應用的結構和行為,從而實現快速開發和靈活擴展。AppML特別適用于構建數據驅動的企業級應用,它可以與各種后端…

pytorch跑手寫體實驗

目錄 1、環境條件 2、代碼實現 3、總結 1、環境條件 pycharm編譯器pytorch依賴matplotlib依賴numpy依賴等等 2、代碼實現 import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import matpl…

burpsuite 設置監聽窗口 火狐利用插件快速切換代理狀態

一、修改burpsuite監聽端口 1、首先打開burpsuite&#xff0c;點擊Proxy下的Options選項&#xff1a; 2、可以看到默認的監聽端口為8080&#xff0c;首先選中我們想要修改的監聽&#xff0c;點擊Edit進行編輯 3、將端口改為9876&#xff0c;并保存 4、可以看到監聽端口修改成功…

typescript學習回顧(五)

今天來分享一下ts的泛型&#xff0c;最后來做一個練習 泛型 有時候&#xff0c;我們在書寫某些函數的時候&#xff0c;會丟失一些類型信息&#xff0c;比如我下面有一個例子&#xff0c;我想提取一個數組的某個索引之前的所有數據 function getArraySomeData(newArr, n:numb…

JVM原理(十):JVM虛擬機調優分析與實戰

1. 大內存硬件上的程序部署策略 這是筆者很久之前處理過的一個案例&#xff0c;但今天仍然具有代表性。一個15萬PV/日左右的在線文檔類型網站最近更換了硬件系統&#xff0c;服務器的硬件為四路志強處理器、16GB物理內存&#xff0c;操作系統為64位CentOS5.4&#xff0c;Resin…

js數組方法歸納——concat、join、reverse

1、concat( ) 用途&#xff1a;可以連接兩個或多個數組&#xff0c;并將新的數組返回該方法不會對原數組產生影響 var arr ["孫悟空","豬八戒","沙和尚"];var arr2 ["白骨精","玉兔精","蜘蛛精"];var arr3 [&…

Vue Router的深度解析

引言 在現代Web應用開發中&#xff0c;客戶端路由已成為實現流暢用戶體驗的關鍵技術。與傳統的服務器端路由不同&#xff0c;客戶端路由通過JavaScript在瀏覽器中控制頁面內容的更新&#xff0c;避免了頁面的全量刷新。Vue Router作為Vue.js官方的路由解決方案&#xff0c;以其…

阿里云centos 取消硬盤掛載并重建數據盤信息再次掛載

一、取消掛載 umount [掛載點或設備] 如果要取消掛載/dev/sdb1分區&#xff0c;可以使用以下命令&#xff1a; umount /dev/sdb1 如果要取消掛載在/mnt/mydisk的掛載點&#xff0c;可以使用以下命令&#xff1a; umount /mnt/mydisk 如果設備正忙&#xff0c;無法立即取消…

【Spring Boot】簡單了解spring boot支持的三種服務器

Tomcat 概述&#xff1a;Tomcat 是 Apache 軟件基金會&#xff08;Apache Software Foundation&#xff09;的 Jakarta EE 項目中的一個核心項目&#xff0c;由 Apache、Sun 和其他一些公司及個人共同開發而成。它作為 Java Servlet、JSP、JavaServer Pages Expression Languag…

系統安全及應用(命令)

目錄 一、賬號安全控制 1.1 系統賬號清理 1.2 密碼安全控制 1.3 歷史記錄控制 1.4 終端自動注銷 二、系統引導和登陸控制 2.1 限制su命令用戶 2.2 PAM安全認證 示例一&#xff1a;通過pam 模塊來防止暴力破解ssh 2.3 sudo機制提升權限 2.3.1 sudo命令&#xff08;ro…

Java的日期類常用方法

Java_Date 第一代日期類 獲取當前時間 Date date new Date(); System.out.printf("當前時間" date); 格式化時間信息 SimpleDateFormat simpleDateFormat new SimpleDateFormat("yyyy-mm-dd hh:mm:ss E); System.out.printf("格式化后時間" si…

【windows|012】光貓、路由器、交換機詳解

&#x1f341;博主簡介&#xff1a; &#x1f3c5;云計算領域優質創作者 &#x1f3c5;2022年CSDN新星計劃python賽道第一名 &#x1f3c5;2022年CSDN原力計劃優質作者 ? &#x1f3c5;阿里云ACE認證高級工程師 ? &#x1f3c5;阿里云開發者社區專家博主 &#x1f48a;交流社…

windows USB 驅動開發-URB結構

通用串行總線 (USB) 客戶端驅動程序無法直接與其設備通信。 相反&#xff0c;客戶端驅動程序會創建請求并將其提交到 USB 驅動程序堆棧進行處理。 在每個請求中&#xff0c;客戶端驅動程序提供一個可變長度的數據結構&#xff0c;稱為 USB 請求塊 (URB) &#xff0c;URB 結構描…

ctfshow-web入門-命令執行(web75-web77)

目錄 1、web75 2、web76 3、web77 1、web75 使用 glob 協議繞過 open_basedir&#xff0c;讀取根目錄下的文件&#xff0c;payload&#xff1a; c?><?php $anew DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString(). ); } ex…

讀書筆記-Java并發編程的藝術-第3章(Java內存模型)-第9節(Java內存模型綜述)

3.9 Java內存模型綜述 前面對Java內存模型的基礎知識和內存模型的具體實現進行了說明。下面對Java內存模型的相關知識做一個總結。 3.9.1 處理器的內存模型 順序一致性內存模型是一個理論參考模型&#xff0c;JMM和處理器內存模型在設計時通常會以順序一致性內存模型為參照。…