<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Python生成器表達(dá)式詳解(含與列表推導(dǎo)式核心對(duì)比、別名探討)

      從“囤貨”到“現(xiàn)做”:Python生成器表達(dá)式詳解(含與列表推導(dǎo)式核心對(duì)比)

      在Python中,處理數(shù)據(jù)時(shí)經(jīng)常會(huì)遇到一個(gè)矛盾:既要簡(jiǎn)潔的語法,又要避免大量數(shù)據(jù)占用內(nèi)存。列表推導(dǎo)式雖能簡(jiǎn)化代碼,卻會(huì)“一次性生成所有元素”,面對(duì)大數(shù)據(jù)時(shí)容易引發(fā)內(nèi)存爆炸;而生成器表達(dá)式恰好解決了這個(gè)問題——它采用“惰性求值”,像“現(xiàn)做現(xiàn)賣”的小吃攤,需要時(shí)才生成元素,不占多余內(nèi)存。本文通過10+實(shí)例,帶你吃透生成器表達(dá)式,同時(shí)厘清它與列表推導(dǎo)式的核心區(qū)別。

      一、先搞懂:生成器表達(dá)式是什么?一句話+一個(gè)對(duì)比

      生成器表達(dá)式(Generator Expression)是一種創(chuàng)建生成器(Generator)的簡(jiǎn)潔語法,本質(zhì)是“延遲產(chǎn)生元素的迭代器”。它的語法和列表推導(dǎo)式幾乎一樣,唯一區(qū)別是:

      • 列表推導(dǎo)式用 [] 包裹,生成列表(立即求值);
      • 生成器表達(dá)式用 () 包裹,生成生成器對(duì)象(延遲求值)。

      先看一個(gè)直觀對(duì)比,同樣是生成1-5的整數(shù):

      # 列表推導(dǎo)式:[]包裹,立即生成完整列表
      list_expr = [i for i in range(1, 6)]
      print(type(list_expr))  # 輸出:<class 'list'>
      print(list_expr)        # 輸出:[1, 2, 3, 4, 5](直接看到所有元素)
      
      # 生成器表達(dá)式:()包裹,生成生成器對(duì)象(無立即元素)
      gen_expr = (i for i in range(1, 6))
      print(type(gen_expr))   # 輸出:<class 'generator'>
      print(gen_expr)         # 輸出:<generator object <genexpr> at 0x...>(看不到元素)
      

      關(guān)鍵差異:列表推導(dǎo)式直接“吐出”所有元素,生成器表達(dá)式只返回一個(gè)“生成器對(duì)象”——你需要主動(dòng)“催它”,它才會(huì)生成下一個(gè)元素(用 next() 函數(shù)或循環(huán)迭代)。

      二、生成器表達(dá)式基礎(chǔ)用法:如何“催它”產(chǎn)生元素?

      生成器對(duì)象是可迭代對(duì)象(支持 for 循環(huán)),但不支持索引訪問(因?yàn)樵剡€沒生成)。獲取元素的核心方式有兩種:next() 函數(shù)和 for 循環(huán)。

      1. 用 next() 函數(shù)“逐個(gè)催更”

      next() 函數(shù)會(huì)觸發(fā)生成器生成“下一個(gè)元素”,直到?jīng)]有元素時(shí)拋出 StopIteration 異常(循環(huán)時(shí)會(huì)自動(dòng)處理這個(gè)異常,無需手動(dòng)捕獲)。

      # 定義生成器表達(dá)式:生成1-3的整數(shù)
      gen = (i for i in range(1, 4))
      
      # 第一次調(diào)用next():生成第一個(gè)元素1
      print(next(gen))  # 輸出:1
      # 第二次調(diào)用next():生成第二個(gè)元素2
      print(next(gen))  # 輸出:2
      # 第三次調(diào)用next():生成第三個(gè)元素3
      print(next(gen))  # 輸出:3
      # 第四次調(diào)用next():沒有元素了,拋出異常
      # print(next(gen))  # 報(bào)錯(cuò):StopIteration
      

      2. 用 for 循環(huán)“批量催更”(推薦)

      for 循環(huán)會(huì)自動(dòng)調(diào)用 next() 函數(shù),直到生成器耗盡,且無需處理 StopIteration 異常,是使用生成器表達(dá)式的主流方式:

      # 生成器表達(dá)式:將1-5的每個(gè)數(shù)翻倍
      double_gen = (i * 2 for i in range(1, 6))
      
      # for循環(huán)迭代生成器
      for num in double_gen:
          print(num, end=" ")  # 輸出:2 4 6 8 10(逐個(gè)生成,不是一次性)
      

      3. 帶條件的生成器表達(dá)式

      和列表推導(dǎo)式一樣,生成器表達(dá)式也支持 if 篩選和 if-else 分支,語法完全一致:

      # 場(chǎng)景1:篩選1-10中的偶數(shù)(if篩選)
      even_gen = (i for i in range(1, 11) if i % 2 == 0)
      print(list(even_gen))  # 輸出:[2, 4, 6, 8, 10](用list()強(qiáng)制生成所有元素)
      
      # 場(chǎng)景2:1-10中偶數(shù)翻倍,奇數(shù)轉(zhuǎn)0(if-else分支)
      process_gen = (i * 2 if i % 2 == 0 else 0 for i in range(1, 11))
      print(list(process_gen))  # 輸出:[0, 4, 0, 8, 0, 12, 0, 16, 0, 20]
      

      三、核心重點(diǎn):生成器表達(dá)式 vs 列表推導(dǎo)式,4大關(guān)鍵區(qū)別

      很多人會(huì)混淆兩者,但它們?cè)?strong>內(nèi)存占用、求值方式、返回類型、可迭代次數(shù)上有本質(zhì)區(qū)別。下面用“對(duì)比表+實(shí)例”講透:

      對(duì)比維度 列表推導(dǎo)式(List Comprehension) 生成器表達(dá)式(Generator Expression)
      語法標(biāo)識(shí) [] 包裹 () 包裹(括號(hào)可省略,如在函數(shù)參數(shù)中)
      求值方式 立即求值(一次性生成所有元素) 延遲求值(迭代時(shí)才生成下一個(gè)元素)
      內(nèi)存占用 高(存儲(chǔ)完整列表,數(shù)據(jù)越多占用越大) 極低(僅存儲(chǔ)生成邏輯,不存元素)
      返回類型 list 對(duì)象(支持索引、切片、多次迭代) generator 對(duì)象(不支持索引,僅一次迭代)

      區(qū)別1:內(nèi)存占用——生成器表達(dá)式“幾乎不占內(nèi)存”

      這是兩者最核心的區(qū)別。用 sys.getsizeof() 函數(shù)可以直觀看到內(nèi)存差異(單位:字節(jié)):

      import sys
      
      # 場(chǎng)景:生成100萬個(gè)整數(shù)
      n = 1_000_000
      
      # 列表推導(dǎo)式:占用大量?jī)?nèi)存(存儲(chǔ)100萬個(gè)整數(shù))
      list_big = [i for i in range(n)]
      print(f"列表推導(dǎo)式內(nèi)存:{sys.getsizeof(list_big)} 字節(jié)")  # 輸出:約8448728字節(jié)(≈8MB)
      
      # 生成器表達(dá)式:幾乎不占內(nèi)存(僅存儲(chǔ)生成邏輯)
      gen_big = (i for i in range(n))
      print(f"生成器表達(dá)式內(nèi)存:{sys.getsizeof(gen_big)} 字節(jié)")  # 輸出:約112字節(jié)(固定大小)
      

      結(jié)論:數(shù)據(jù)量越大,生成器表達(dá)式的內(nèi)存優(yōu)勢(shì)越明顯。處理1000萬、1億條數(shù)據(jù)時(shí),列表推導(dǎo)式可能直接導(dǎo)致內(nèi)存溢出,而生成器表達(dá)式依然輕松應(yīng)對(duì)。

      區(qū)別2:求值方式——列表“囤貨”,生成器“現(xiàn)做”

      列表推導(dǎo)式在定義時(shí)就會(huì)“一次性生成所有元素”(囤貨),而生成器表達(dá)式只在迭代時(shí)才“生成下一個(gè)元素”(現(xiàn)做)。用 print 語句可以直觀看到這個(gè)差異:

      # 列表推導(dǎo)式:定義時(shí)就執(zhí)行print,一次性輸出所有“生成中”
      print("列表推導(dǎo)式執(zhí)行:")
      list_with_print = [print(f"列表生成:{i}") for i in range(1, 4)]
      # 輸出:
      # 列表推導(dǎo)式執(zhí)行:
      # 列表生成:1
      # 列表生成:2
      # 列表生成:3
      
      # 生成器表達(dá)式:定義時(shí)不執(zhí)行print,迭代時(shí)才輸出
      print("\n生成器表達(dá)式執(zhí)行:")
      gen_with_print = (print(f"生成器生成:{i}") for i in range(1, 4))
      print("生成器已定義,但未生成元素")  # 此時(shí)無print輸出
      # 迭代生成器:才執(zhí)行print
      for _ in gen_with_print:
          pass
      # 輸出:
      # 生成器已定義,但未生成元素
      # 生成器生成:1
      # 生成器生成:2
      # 生成器生成:3
      

      結(jié)論:列表推導(dǎo)式“先做事,再給結(jié)果”,生成器表達(dá)式“先承諾,用的時(shí)候再做事”——這種延遲求值讓它能處理“無法一次性加載到內(nèi)存”的數(shù)據(jù)(如大文件)。

      區(qū)別3:返回類型——列表支持索引,生成器不支持

      列表推導(dǎo)式返回 list 對(duì)象,支持索引、切片、多次迭代;生成器表達(dá)式返回 generator 對(duì)象,不支持索引(元素未生成),且只能迭代一次(迭代完元素就“耗盡”了):

      # 列表推導(dǎo)式:支持索引和多次迭代
      list_expr = [1, 2, 3]
      print(list_expr[0])  # 輸出:1(支持索引)
      # 多次迭代:每次都能拿到完整元素
      for _ in range(2):
          print(list(list_expr), end=" ")  # 輸出:[1,2,3] [1,2,3]
      
      # 生成器表達(dá)式:不支持索引,僅一次迭代
      gen_expr = (1, 2, 3)  # 注意:這是元組!生成器表達(dá)式需用(i for i in ...)
      gen_expr = (i for i in [1, 2, 3])
      # print(gen_expr[0])  # 報(bào)錯(cuò):TypeError: 'generator' object is not subscriptable(不支持索引)
      # 第一次迭代:能拿到元素
      print("\n第一次迭代生成器:")
      for num in gen_expr:
          print(num, end=" ")  # 輸出:1 2 3
      # 第二次迭代:生成器已耗盡,無元素
      print("\n第二次迭代生成器:")
      for num in gen_expr:
          print(num, end=" ")  # 輸出:(空)
      

      結(jié)論:如果需要多次訪問元素、或用索引定位元素,用列表推導(dǎo)式;如果只需迭代一次、且數(shù)據(jù)量大,用生成器表達(dá)式。

      區(qū)別4:配合內(nèi)置函數(shù)——生成器更省內(nèi)存

      Python的內(nèi)置函數(shù)(如 summaxanyall)支持接收可迭代對(duì)象,此時(shí)用生成器表達(dá)式比列表推導(dǎo)式更省內(nèi)存(無需先生成完整列表):

      # 場(chǎng)景:計(jì)算1-100萬的和
      n = 1_000_000
      
      # 用列表推導(dǎo)式:先生成100萬元素的列表,再求和(占內(nèi)存)
      sum_list = sum([i for i in range(n)])
      
      # 用生成器表達(dá)式:直接迭代求和,不生成列表(省內(nèi)存)
      sum_gen = sum(i for i in range(n))  # 括號(hào)可省略,更簡(jiǎn)潔
      
      print(sum_list == sum_gen)  # 輸出:True(結(jié)果相同)
      

      技巧:當(dāng)內(nèi)置函數(shù)只需迭代一次數(shù)據(jù)時(shí),生成器表達(dá)式的括號(hào)可以省略(如 sum(i for i in ...)),比列表推導(dǎo)式更簡(jiǎn)潔。

      四、生成器表達(dá)式的3個(gè)高頻使用場(chǎng)景(附實(shí)例)

      生成器表達(dá)式的核心優(yōu)勢(shì)是“內(nèi)存友好”和“延遲求值”,以下場(chǎng)景中它比列表推導(dǎo)式更適合:

      場(chǎng)景1:處理大文件(逐行讀取,不占內(nèi)存)

      讀取幾GB的大文件時(shí),用 readlines() 會(huì)一次性加載所有行到內(nèi)存(容易溢出),而生成器表達(dá)式可以逐行迭代,內(nèi)存占用極低:

      # 場(chǎng)景:統(tǒng)計(jì)大文件中包含“error”的行數(shù)(文件大小10GB+)
      def count_error_lines(file_path):
          # 生成器表達(dá)式:逐行讀取文件,不加載所有行到內(nèi)存
          error_lines = (line for line in open(file_path, "r", encoding="utf-8") if "error" in line.lower())
          # 迭代生成器,統(tǒng)計(jì)行數(shù)
          count = 0
          for _ in error_lines:
              count += 1
          return count
      
      # 調(diào)用函數(shù):內(nèi)存占用始終很低(≈100字節(jié))
      print(f"包含'error'的行數(shù):{count_error_lines('big_file.log')}")
      

      場(chǎng)景2:生成大量數(shù)據(jù)(無需存儲(chǔ),直接迭代)

      需要生成百萬、千萬級(jí)數(shù)據(jù)時(shí),生成器表達(dá)式可以“用多少生成多少”,避免內(nèi)存爆炸:

      # 場(chǎng)景:生成1000萬個(gè)隨機(jī)數(shù),篩選出大于0.5的數(shù)
      import random
      
      # 生成器表達(dá)式:生成1000萬隨機(jī)數(shù),篩選大于0.5的
      random_gen = (random.random() for _ in range(10_000_000))
      filtered_gen = (num for num in random_gen if num > 0.5)
      
      # 統(tǒng)計(jì)篩選后的數(shù)量(無需存儲(chǔ)所有數(shù)據(jù))
      count = 0
      for _ in filtered_gen:
          count += 1
      print(f"大于0.5的隨機(jī)數(shù)數(shù)量:{count}")  # 輸出:約500萬(符合概率)
      

      場(chǎng)景3:嵌套生成器表達(dá)式(處理多維數(shù)據(jù),省內(nèi)存)

      和列表推導(dǎo)式一樣,生成器表達(dá)式也支持嵌套,但內(nèi)存占用遠(yuǎn)低于嵌套列表推導(dǎo)式。比如展平二維列表:

      # 場(chǎng)景:展平1000個(gè)嵌套子列表(每個(gè)子列表1000個(gè)元素)
      big_matrix = [[i for i in range(1000)] for _ in range(1000)]  # 100萬元素的二維列表
      
      # 嵌套生成器表達(dá)式:展平二維列表,不占內(nèi)存
      flat_gen = (num for sublist in big_matrix for num in sublist)
      
      # 迭代展平后的生成器(內(nèi)存占用極低)
      total = 0
      for num in flat_gen:
          total += num
      print(f"所有元素的和:{total}")  # 輸出:499999500000(正確結(jié)果)
      

      五、使用生成器表達(dá)式的3個(gè)注意事項(xiàng)

      1. 生成器只能迭代一次:迭代完后,生成器就“空了”,再次迭代不會(huì)有元素。如果需要多次迭代,應(yīng)重新定義生成器表達(dá)式,或轉(zhuǎn)為列表(小數(shù)據(jù)場(chǎng)景)。

        gen = (i for i in range(3))
        print(list(gen))  # 輸出:[1,2,3](第一次迭代)
        print(list(gen))  # 輸出:[](第二次迭代,已耗盡)
        
      2. 不支持索引和切片:生成器的元素未生成,無法通過 gen[0]gen[1:3] 訪問,只能通過 next()for 循環(huán)迭代。

      3. 復(fù)雜邏輯需拆分:和列表推導(dǎo)式一樣,避免過度嵌套(如三層以上),否則可讀性會(huì)變差。復(fù)雜邏輯建議拆分成函數(shù),再在生成器表達(dá)式中調(diào)用:

        # 復(fù)雜邏輯:判斷一個(gè)數(shù)是否為質(zhì)數(shù)(拆分成函數(shù))
        def is_prime(n):
            if n < 2:
                return False
            for i in range(2, int(n**0.5)+1):
                if n % i == 0:
                    return False
            return True
        
        # 生成器表達(dá)式:篩選1-1000中的質(zhì)數(shù)(邏輯清晰)
        prime_gen = (n for n in range(1, 1001) if is_prime(n))
        

      六、總結(jié):什么時(shí)候用生成器表達(dá)式?什么時(shí)候用列表推導(dǎo)式?

      選擇依據(jù) 推薦使用生成器表達(dá)式 推薦使用列表推導(dǎo)式
      數(shù)據(jù)量 大數(shù)據(jù)(10萬+)或未知大小的數(shù)據(jù) 小數(shù)據(jù)(1萬以內(nèi))
      內(nèi)存限制 內(nèi)存緊張(如服務(wù)器、嵌入式設(shè)備) 內(nèi)存充足
      迭代次數(shù) 只需迭代一次(如求和、篩選后直接用) 需要多次迭代(如反復(fù)查詢、修改元素)
      訪問方式 僅需順序迭代(無需索引) 需要索引、切片、修改元素

      一句話總結(jié):小數(shù)據(jù)、多次用、需索引 → 列表推導(dǎo)式;大數(shù)據(jù)、一次用、省內(nèi)存 → 生成器表達(dá)式

      生成器表達(dá)式是Python“優(yōu)雅且高效”的典型體現(xiàn)——它既保留了列表推導(dǎo)式的簡(jiǎn)潔語法,又解決了大數(shù)據(jù)場(chǎng)景下的內(nèi)存問題。學(xué)會(huì)它,你處理數(shù)據(jù)時(shí)會(huì)更從容,再也不用為“內(nèi)存不夠”發(fā)愁~

      名稱探討

      生成器表達(dá)式和列表推導(dǎo)式的“其他叫法”,主要來自 簡(jiǎn)稱翻譯差異(因英文術(shù)語“Comprehension”的翻譯不同),社區(qū)中常用的別名不多,核心是“簡(jiǎn)化稱呼”和“統(tǒng)一認(rèn)知”,具體如下:

      一、列表推導(dǎo)式的其他叫法

      列表推導(dǎo)式的英文是 List Comprehension,中文社區(qū)里最常見的別名是“簡(jiǎn)化版稱呼”或“翻譯變體”,沒有特別生僻的術(shù)語:

      1. 列表推導(dǎo)(最常用簡(jiǎn)稱)
        因?yàn)椤巴茖?dǎo)式”的“式”字可省略,且不影響語義,比如“用列表推導(dǎo)創(chuàng)建一個(gè)列表”,這是日常交流中最普遍的叫法(比如開發(fā)者會(huì)說“這段邏輯用列表推導(dǎo)更簡(jiǎn)潔”,而不是完整說“列表推導(dǎo)式”)。

      2. 列表解析式(翻譯變體)
        “Comprehension”在編程語境中除了“推導(dǎo)”,也常被翻譯為“解析”,因此“列表解析式”是另一種常見叫法,和“列表推導(dǎo)式”完全等價(jià)(比如部分教程或書籍會(huì)用“列表解析式”,但邏輯和用法完全一樣)。

      注意:沒有“列表括號(hào)式”“列表循環(huán)式”這類標(biāo)準(zhǔn)叫法,避免使用不規(guī)范的稱呼,以免造成誤解。

      二、生成器表達(dá)式的其他叫法

      生成器表達(dá)式的英文是 Generator Expression,別名同樣以“簡(jiǎn)稱”和“翻譯變體”為主,且需注意和“生成器函數(shù)”區(qū)分(避免混淆):

      1. 生成器推導(dǎo)(最常用簡(jiǎn)稱)
        對(duì)應(yīng)列表推導(dǎo)的簡(jiǎn)化邏輯,省略“式”字,比如“用生成器推導(dǎo)處理大數(shù)據(jù)”,是社區(qū)中對(duì)生成器表達(dá)式的常見簡(jiǎn)稱,既簡(jiǎn)潔又能明確指向“表達(dá)式”(而非生成器函數(shù))。

      2. 生成器解析式(翻譯變體)
        同理,“Comprehension”翻譯為“解析”時(shí),就叫“生成器解析式”,和“生成器表達(dá)式”等價(jià),比如“生成器解析式比列表解析式更省內(nèi)存”。

      注意:避免兩個(gè)誤區(qū):

      • 不要叫“生成器函數(shù)”:生成器函數(shù)是用 def 定義、含 yield 關(guān)鍵字的函數(shù)(如 def gen(): yield 1),和“生成器表達(dá)式”(括號(hào)包裹的推導(dǎo)語法)是兩種不同的生成器創(chuàng)建方式;
      • 不要叫“括號(hào)推導(dǎo)式”:雖然生成器表達(dá)式用 () 包裹,但“括號(hào)推導(dǎo)式”不是標(biāo)準(zhǔn)叫法,且可能和元組(() 定義)混淆,不建議使用。

      三、總結(jié):常用別名對(duì)照表

      為了更清晰,整理成表格,方便你記憶和區(qū)分:

      正式名稱 常用別名1(簡(jiǎn)稱) 常用別名2(翻譯變體) 不建議的叫法
      列表推導(dǎo)式 列表推導(dǎo) 列表解析式 列表括號(hào)式、列表循環(huán)式
      生成器表達(dá)式 生成器推導(dǎo) 生成器解析式 生成器函數(shù)、括號(hào)推導(dǎo)式

      簡(jiǎn)單說:日常交流中,用“列表推導(dǎo)”“生成器推導(dǎo)”最簡(jiǎn)潔;看資料時(shí)遇到“解析式”,知道和“推導(dǎo)式”是一回事即可,無需糾結(jié)——核心是能通過稱呼明確指向?qū)?yīng)的語法,避免和其他概念(如生成器函數(shù)、普通列表/生成器)混淆。

      posted @ 2025-11-03 20:59  wangya216  閱讀(17)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产网红主播精品一区| 精品乱人伦一区二区三区| 麻豆国产传媒精品视频| 天堂在/线中文在线资源 官网| 亚洲中文字幕亚洲中文精| 国产精品中文字幕久久| 方山县| 国产日韩入口一区二区| 又大又黄又粗高潮免费| 久久精品国产再热青青青| 久久国产成人午夜av影院| 久久精品人人做人人爽97| 日本免费观看mv免费版视频网站| 亚洲不卡一区二区在线看| 男人下部进女人下部视频| 国产午夜福利视频第三区| 国产高清自产拍AV在线| 国产无遮挡猛进猛出免费软件| 国产av综合一区二区三区| 巨熟乳波霸若妻在线播放| 五月天国产成人av免费观看| 亚洲一区二区三区在线观看精品中文 | 久久亚洲精品11p| 国产成人无码AV片在线观看不卡 | 亚洲免费观看一区二区三区| 免费一区二三区三区蜜桃| 亚洲日韩国产成网在线观看| av无码久久久久不卡网站蜜桃| 久热久热免费在线观视频| 国产av剧情md精品麻豆| 92自拍视频爽啪在线观看| 人妻系列无码专区免费| 亚洲五月天综合| 色综合天天综合天天综| 亚洲 制服 丝袜 无码| 亚洲精品国产无套在线观| 欧洲精品色在线观看| 日本深夜福利在线观看| 国产一区二区三区色老头| 日韩精品av一区二区三区| 四虎在线永久免费看精品|