python3 生成器表達式

来源:https://www.cnblogs.com/yund/archive/2023/05/01/17366967.html
-Advertisement-
Play Games

Springboot的優點 內置servlet容器,不需要在伺服器部署 tomcat。只需要將項目打成 jar 包,使用 java -jar xxx.jar一鍵式啟動項目 SpringBoot提供了starter,把常用庫聚合在一起,簡化複雜的環境配置,快速搭建spring應用環境 可以快速創建獨立 ...


在 Python3 中,生成器表達式是一種語言結構,它可以快速地創建一個可迭代對象。生成器表達式類似於列表推導式,但使用圓括弧而不是方括弧,並且返回的是一個生成器對象而不是一個列表。

在 Python3 中,生成器表達式有兩種類型:生成器函數和生成器表達式。

  1. 生成器函數:

生成器函數是一種特殊的函數,在函數中使用 yield 語句來生成一個值,然後暫停函數執行並保留當前狀態,等待下一次調用時繼續執行。生成器函數的優點是可以處理大量數據,因為它們只需要在記憶體中保存一個值,而不是全部保存在記憶體中。

例如,以下是一個生成器函數,它可以生成斐波那契數列中的前 n 個數字:

def fibonacci(n):
    a, b = 0, 1
    for i in range(n):
        yield a
        a, b = b, a + b
  1. 生成器表達式:

生成器表達式是使用圓括弧包圍的表達式,其中包含一個 for 迴圈和一個可選的 if 條件。生成器表達式可以用來生成一個序列,這個序列可以通過迭代訪問,但不必事先將所有元素保存在記憶體中。

例如,以下生成器表達式可以生成一個包含從 1 到 10 的偶數的生成器對象:

gen = (i for i in range(1, 11) if i % 2 == 0)

註意事項:

  1. 生成器表達式可以節省記憶體空間,但是如果需要多次使用生成器對象中的值,則需要將其轉換為列表或其他數據結構。
  2. 如果生成器表達式中的代碼太長或複雜,則建議使用生成器函數來代替,以提高代碼的可讀性和可維護性。
  3. 如果生成器表達式中的代碼有副作用(例如修改了全局變數),則可能會導致意外行為,應該避免這種情況。
  4. 生成器表達式可以嵌套,但是應該註意不要嵌套過深導致代碼難以理解。例如:
    gen = ((i, j) for i in range(1, 4) for j in range(4, 7))

    這個生成器表達式可以生成一個包含所有 (1,4) 到 (3,6) 的元組的生成器對象。

  5. 生成器表達式中的 for 迴圈可以有多個,每個迴圈可以使用一個 if 條件。例如:
    gen = (i * j for i in range(1, 4) if i % 2 == 0 for j in range(4, 7) if j % 2 != 0)

    這個生成器表達式可以生成一個包含所有偶數 i 與奇數 j 的乘積的生成器對象。

  6. 生成器表達式中的變數作用域只在生成器表達式內部,不會泄露到外部。例如:
    x = 10
    gen = (x for x in range(1, 5))
    print(list(gen))    # 輸出 [1, 2, 3, 4]
    print(x)    # 輸出 10,說明 x 只在生成器表達式內部存在,不會影響外部變數 x 的值。
  7. 生成器表達式可以和其他 Python 的內置函數或模塊一起使用,例如 map、filter、itertools 等。例如:
    import itertools
    
    # 使用 map 函數和生成器表達式生成一個列表,其中每個元素都是平方數。
    lst = list(map(lambda x: x ** 2, (i for i in range(1, 5))))
    print(lst)    # 輸出 [1, 4, 9, 16]
    
    # 使用 itertools 模塊中的 zip_longest 函數和生成器表達式生成一個包含所有輸入迭代器的元組的列表。
    lst = list(itertools.zip_longest((i for i in range(1, 5)), ('a', 'b', 'c')))
    print(lst)    # 輸出 [(1, 'a'), (2, 'b'), (3, 'c'), (4, None)]
  8. 在使用生成器表達式時,應該儘可能地使用惰性求值,即只生成需要的元素,並且在使用完之後立即釋放相應的資源。這樣可以避免不必要的記憶體占用和性能問題。
  9. 處理大型數據集,例如從文件或資料庫中讀取數據,並將其用作生成器表達式的輸入。這樣可以避免一次性載入所有數據,並且節省記憶體空間。
    with open('data.txt') as f:
        gen = (line.strip() for line in f if 'error' in line)
        for item in gen:
            print(item)
  10. 通過生成器表達式實現惰性求值,例如只有當需要時才計算函數的值。這樣可以避免不必要的計算和記憶體占用。
    def expensive_function(n):
        print(f"Calculating {n}...")
        return n ** 2
    
    gen = (expensive_function(i) for i in range(5))
    print(list(gen))    # 輸出 Calculating 0... Calculating 1... Calculating 2... Calculating 3... Calculating 4... [0, 1, 4, 9, 16]

    這個例子中,我們定義了一個函數 expensive_function,並使用一個生成器表達式來生成一個包含前五個數字的平方的列表。在評估生成器表達式時,expensive_function 只有在需要計算平方時才被調用,這樣可以避免不必要的計算和記憶體占用。

  11. 在多個迭代器之間生成元素,例如合併兩個排序列表並返回一個新的排序列表。
    def merge_sorted(lst1, lst2):
        i, j = 0, 0
        while i < len(lst1) and j < len(lst2):
            if lst1[i] <= lst2[j]:
                yield lst1[i]
                i += 1
            else:
                yield lst2[j]
                j += 1
        yield from lst1[i:]
        yield from lst2[j:]
    
    lst1 = [1, 3, 5, 7]
    lst2 = [2, 4, 6, 8]
    gen = merge_sorted(lst1, lst2)
    print(list(gen))    # 輸出 [1, 2, 3, 4, 5, 6, 7, 8]

    這個例子中,我們定義了一個 merge_sorted 函數來合併兩個排序列表,並返回一個新的排序列表。在函數中,我們使用一個生成器函數來生成所有排好序的元素,併在函數返回之前返回它們。這個方法可以在處理大型數據集時節省記憶體空間,並且可以避免不必要的排序或其他操作。

  12. 用於過濾和轉換數據,例如將一個列表中的所有元素轉換為字元串並刪除其中的空格。
    lst = [' hello ', ' world', '', 'python', '']
    gen = (s.strip() for s in lst if s)
    print(list(gen))    # 輸出 ['hello', 'world', 'python']

    這個例子中,我們使用一個生成器表達式來對列表中的所有元素進行過濾和轉換。具體來說,我們首先使用 if 子句來過濾出所有不為空的字元串,然後使用 strip 方法來刪除每個字元串的前導和尾隨空格。最後,我們將經過處理的字元串返回為一個生成器對象,並將其轉換為一個列表。

  13. 生成器表達式可以與其他 Python 內置函數(如 map 和 filter)和模塊(如 itertools)結合使用,以實現更高效和優雅的代碼。

  14. 在使用生成器表達式時,應該儘可能地使用惰性求值,即只生成需要的元素,併在使用完之後立即釋放相應的資源。這樣可以避免不必要的記憶體占用和性能問題。

  15. 如果生成器表達式中的代碼有副作用(例如修改了全局變數),則可能會導致意外行為,應該避免這種情況。

  16. 在編寫長的生成器表達式時,建議將其分解成多個簡單的表達式或生成器函數,以提高代碼的可讀性和可維護性。

  17. 在使用生成器表達式時,應該學會使用列表推導式和普通的 for 迴圈來進行比較,以選擇最適合特定任務的工具。

  18. 最後,需要註意的是,生成器表達式雖然非常強大和方便,但也並非萬能的。在某些情況下,還是需要使用其他語言結構或演算法來解決問題。

  19. 在使用生成器表達式時,應該避免使用過多的嵌套迴圈和條件語句,以免代碼變得難以閱讀和維護。在這種情況下,建議考慮使用其他數據結構或演算法。

  20. 使用生成器表達式時,應該儘可能地保持代碼簡單和易讀。這包括命名變數、註釋代碼和格式化輸出,以便其他人可以理解你的代碼。

  21. 在使用生成器表達式時,需要註意一些性能問題。例如,在處理大型數據集時,可能需要考慮使用並行計算或其他優化演算法來提高效率。讓我們來看一個例子,說明生成器表達式和列表推導式之間的差異:

讓我們來看一個例子,說明生成器表達式和列表推導式之間的差異:

# 列表推導式
lst = [i ** 2 for i in range(1, 11)]
print(lst)

# 生成器表達式
gen = (i ** 2 for i in range(1, 11))
print(list(gen))

個例子中,我們首先使用列表推導式創建一個包含前 10 個數字的平方的列表。然後,我們使用一個生成器表達式來創建一個包含相同元素的生成器對象,並將其轉換為一個列表。

一般來說,列表推導式比起生成器表達式更加適合小型數據集,因為它們可以在記憶體中完全構建出一個列表,並且可以在需要時隨時進行索引和修改。另一方面,生成器表達式更適合大型數據集,因為它們只返回必要的元素,而且可以逐個處理每個元素,從而節省記憶體空間。

在實際編程中,我們應該根據具體情況選擇最適合的工具,並權衡各種因素(例如代碼的可讀性、效率、記憶體占用等)。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在前兩篇: .NET Core部署到linux(CentOS)最全解決方案,常規篇 .NET Core部署到linux(CentOS)最全解決方案,進階篇(Supervisor+Nginx) 我們對.netcore部署到linux有了一個充分的瞭解,已經可以滿足應用要求了,這篇文章我們繼續深入... ...
  • 這一篇簡單說明 CH32V208 的片記憶體儲結構和時鐘的特點, 以及通過 SDK 中的示例代碼分析 CH32V208 的時鐘設置 ...
  • CH32V208系列是沁恆32位RISC-V中比較新的一個系列, 基於青稞RISC-V4C內核, 最高144MHz主頻, 64KB SRAM,128KB Flash, 供電電壓2.5/3.3V. 這個型號的特點: 除了特有的硬體堆棧區、快速中斷入口, 片上集成了2Mbps低功耗藍牙BLE 5.3, ... ...
  • (初探MySQL) 前言 周所周知MySQL已成為全世界最受歡迎的資料庫之一。無論你用的何種編程語言在開發系統,資料庫基本上都是必不可少的。 無論是小型項目開發如我們開發一個個人博客系統,還是構建那些聲名顯赫的網站如某寶、某訊等,MySQL都有著穩定、可靠、快速等優點。可以勝任數據存儲的業務需求。 ...
  • 1. 消滅NULL 1.1. NULL惹人討厭的原因 1.1.1. 進行SQL編碼時,必須考慮違反人類直覺的三值邏輯 1.1.2. 指定IS NULL、IS NOT NULL的時候,不會用到索引,SQL語句執行起來性能低下 1.1.2.1. 1 + NULL = NULL 2- NULL = NUL ...
  • 前言 地址:https://www.cnblogs.com/FReQuenter5156/p/setblog.html/ 如題,使用的是 Simple Memory 主題。 Github 連接:https://github.com/BNDong/Cnblogs-Theme-SimpleMemory。 ...
  • 嘿嘿嘿、嘿嘿,俺又回來了! github代碼地址 https://github.com/Tom-shushu/work-study 介面文檔有道雲 https://note.youdao.com/s/GShGsYE8 介面文檔離線版本 https://files.cnblogs.com/files/ ...
  • FactoryBean 和 BeanFactory 是兩個不同的概念。前者是一個介面,我們可以在實現該介面時通過調用 getObject 方法來返回實例,同時 FactoryBean 本身也是一個實例。後者是 Spring 容器的工廠,通過其中的 bean 定義 Map 一個一個地實例化我們通過註解... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...