日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【python】生成器

發布時間:2023/12/20 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【python】生成器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

生成器

直接總結

  • 創建生成器的方法
  • 生成器表達式:(i for i in [1, 2])
  • yield: 函數中出現yield這個函數就是生成器,函數(生成器)執行到yield時會返回yield后面的值,并暫停,知道下次被喚醒后會從暫停處接著執行
  • 迭代生成器: 生成器實現了python迭代協議,可以使用next()或for迭代
  • 向生成器發送消息:如果yield出現在表達式右邊,下一次生成器被send()喚醒時,上一個yield會接收send()發過來的消息賦值給上一個yield左邊的變量。
  • 喚醒生成器:
  • next():喚醒生成器,讓他運行到下一個yield處,返回yield出來的值
  • send():喚醒生成器,并給生成器發送一個消息,同時讓他運行到下一個yield處,返回yield出來的值,不能直接一開始就發送具體的數據
  • 停止生成器:close()
  • 發送異常:throw(type, val)
  • yield from
  • 創建與使用生成器

    直接使用生成器表達式就可以快速創建一個生成器

    gen = (i for i in range(10)) print(type(gen)) for i in gen:print(i, end=" ")# <class 'generator'> # 0 1 2 3 4 5 6 7 8 9

    生成器實現了__next__可以使用next()來獲取下一個值,當然也可以使用for循環遍歷

    更加常見的創建生成器的方式是使用yield關鍵字,一個函數如果出現yield關鍵字這個函數就會變成生成器,當函數運行到yield時會暫停下來,”返回“一個結果,下一次喚醒生成器時,函數會從停下來的地方繼續運行

    def builder_demo():yield 0yield 1return 3if __name__ == '__main__':bd = builder_demo()print(type(bd))print(next(bd))print(next(bd))print(next(bd))print(next(bd)) <class 'generator'> 0 1 Traceback (most recent call last):File "E:/python/coroutine_test.py", line 12, in <module>print(next(bd)) StopIteration: 3

    當沒有下一個元素時調用next會拋出StopIteration異常,return的值會作為異常的值

    if __name__ == '__main__':bd = builder_demo()while True:try:print(next(bd))except StopIteration as e:print(f'result is {e.value}')break 0 1 result is 3

    yield不但可以“傳遞出值”,也可以接收值

    def builder_demo():news = yield 0print(f'news: {news}')news1 = yield 1print(f'new1: {news1}')return 3if __name__ == '__main__':bd = builder_demo()print(next(bd))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2) 0 news: hello 1 new1: hello2 Traceback (most recent call last):File "E:python/coroutine_test.py", line 14, in <module>result2 = bd.send("hello2") StopIteration: 3

    往暫停處傳遞消息使用生成器的send()方法,這個方法還可以自動迭代到生成器中的下一個對象(有next())的作用。

    生成器是先yield出數據,等到下一次生成器被喚醒時,才會接收send()的數據,然后再yield出下一個數據,所以不能一開始就直接調用send()發送具體的值,會拋出TypeError

    TypeError: can't send non-None value to a just-started generator

    應該先執行一次next()或執行一次generator.send(None),讓生成器yield出數據,send(None)的作用與next()基本一樣

    生成器也可以停止,使用close()方法

    def builder_demo():news = yield 0print(f'news: {news}')news1 = yield 1print(f'new1: {news1}')yield 4yield 5return 3if __name__ == '__main__':bd = builder_demo()# print(next(bd))print(bd.send(None))result1 = bd.send("hello")print(result1)result2 = bd.send("hello2")print(result2)bd.close()print(next(bd)) 0 news: hello 1 new1: hello2 4 Traceback (most recent call last):File "E:python/coroutine_test.py", line 20, in <module>print(next(bd)) StopIteration

    在close()之后再使用next(),會拋出StopIteration異常

    除此之外,還可以向生成器發送異常

    if __name__ == '__main__':bd = builder_demo()print(bd.send(None))bd.throw(Exception, TypeError("throw new error"))print(next(bd)) 0 Traceback (most recent call last):File "E:python/coroutine_test.py", line 19, in <module>bd.throw(Exception, TypeError("throw new error"))File "E:python/coroutine_test.py", line 2, in builder_demonews = yield 0 TypeError: throw new error

    yield from

    yield from 是python3.3 PEP380 新添加的特性,它允許將一個生成器的部分操作委派給另一個生成器,除了向子生成器委派任務,yield from也可以直接作用于迭代器,將迭代器中的每個對象逐一yield出來,如:

    def demo(*args, **kwargs):for i in args:for j in i:yield j # 等價于 def demo(*args, **kwargs):for i in args:yield from i

    上面的函數其實就是itertools.chain() 作用是將多個迭代器中的元素迭代出來

    生成器嵌套

    1、調用方:調用委派生成器的客戶端(調用方)代碼
    2、委托生成器:包含yield from表達式的生成器函數
    3、子生成器:yield from后面加的生成器函數

    yield from 可以架設一個調用方到子生成器之間的雙向橋梁

    final_result = {}def calculate():total = 0nums = []while True:info = yieldif not info:breaktotal += infonums.append(info)# return 的值會被賦值給yield from 左邊的變量return total, numsdef middle(key: str, gen):while True:final_result[key] = yield from gen()print(final_result)def main():data = {"apple": [230, 569, 234, 776],"banana": [564, 213, 798, 327],"strawberry": [98, 76, 120, 436, 55],"orange": [78, 67, 345, 124]}for key, value in data.items():# 不要傳遞calculate()!mid = middle(key, calculate)mid.send(None) # 初激for v in value:mid.send(v)mid.send(None)if __name__ == '__main__':main()

    為什么“多此一舉”架設一個“橋梁”?

    • yield from 在內部處理了大量可能的異常,簡化開發,提高代碼安全性和可讀性

    生成器的作用

  • 適用于對大量數據的處理:如果要對產生的大量數據進一步處理時,使用容器就只能先得到所有要處理的數據,存到容器,再逐個對容器中的數據遍歷,再加工,最后得到目標數據,這樣第一步產生的“中間數據”只用一次,但仍需大量空間儲存;使用生成器可以產生一個,加工一個,節約內存,提高效率
  • 用于協程
  • 總結

    以上是生活随笔為你收集整理的【python】生成器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。