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

歡迎訪問 生活随笔!

生活随笔

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

python

Python中的生成器与yield

發布時間:2024/4/15 python 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python中的生成器与yield 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

對于python中的yield有些疑惑,然后在StackOverflow上看到了一篇回答,所以搬運過來了,英文好的直接看原文吧。

可迭代對象

當你創建一個列表的時候,你可以一個接一個地讀取其中的項。一個接一個地讀項就叫做迭代:

>>> mylist = [1, 2, 3] >>> for i in mylist: ... print(i) 1 2 3

mylist就是一個可迭代對象。你使用列表推導式時,就創建了一個列表,也就是一個可迭代對象:

>>> mylist = [x*x for x in range(3)] >>> for i in mylist: ... print(i) 0 1 4

任何可以用“for...in...”操作的事物都是可迭代對象;列表,字符串,文件……

這些可迭代對象很方便,因為你可以隨意地訪問它們,但是你把所有的值都保存在內存中。如果你有大量的數據的話,這就不是你想要的了。

生成器

生成器是迭代器,但是你只可以對它們進行一次迭代。這是因為你沒有在內存中存儲所有數值,它們動態地生成值

>>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ... print(i) 0 1 4

跟上面的例子基本一樣,除了用()代替了[]。但是,你不能第二次執行for i in mygenerator,因為生成器只能使用一次;它計算出0,然后忘掉0并計算1,最后是計算4,一個接一個地進行。

Yield

Yield是一個像return一樣的關鍵字,只不過函數返回的是一個生成器:

>>> def createGenerator(): ... mylist = range(3) ... for i in mylist: ... yield i*i ... >>> mygenerator = createGenerator() # 創建一個迭代器 >>> print(mygenerator) # mygenerator是一個對象! <generator object createGenerator at 0xb7555c34> >>> for i in mygenerator: ... print(i) 0 1 4 >>> for i in mygenerator: print(i)>>>

這個例子里的生成器沒什么用,但是如果你知道你的函數會返回大量的數據,而你只需要對這些數據讀取一次時,那就變得很有用了。

要掌握yield,你必須理解當你訪問函數的時候,你寫在函數體中的代碼并沒有執行。這個函數只是返回了迭代器對象,這一點很微妙。

然后,每次for語句使用生成器的時候,你的代碼就會運行。

然后是最難的部分:

for語句第一次調用從你的函數中創建的迭代器對象時,它就會運行你函數中的代碼,從開始一直到它碰見yield,然后它就返回這個循環中的第一個值。之后,每一次的調用都會再一次運行你寫在函數里的循環,然后返回下一個值,直到沒有值可以被返回。

一旦函數運行但是沒有再碰到yield,生成器就被認為是空的。這可能是因為循環已經結束了,或者因為不再滿足if/else條件了。

控制生成器耗盡

>>> class Bank(): # let's create a bank, building ATMs ... crisis = False ... def create_atm(self): ... while not self.crisis: ... yield "$100" >>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want >>> corner_street_atm = hsbc.create_atm() >>> print(corner_street_atm.next()) $100 >>> print(corner_street_atm.next()) $100 >>> print([corner_street_atm.next() for cash in range(5)]) ['$100', '$100', '$100', '$100', '$100'] >>> hsbc.crisis = True # crisis is coming, no more money! >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs >>> print(wall_street_atm.next()) <type 'exceptions.StopIteration'> >>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business >>> for cash in brand_new_atm: ... print cash $100 $100 $100 $100 $100 $100 $100 $100 $100 ...

這個在很多方面都有用,比如控制對某個資源的訪問。

Itertools,好幫手

itertools模塊包含操作可迭代對象的特殊函數。想要復制一個生成器?連接兩個生成器?把嵌套列表中的數據整理到一個列表中?不創建另一個列表就直接Map/Zip?

那就import itertools。

例子?那我們看看4馬比賽中所有可能的到達順序(全排列):

>>> horses = [1, 2, 3, 4] >>> races = itertools.permutations(horses) >>> print(races) <itertools.permutations object at 0xb754f1dc> >>> print(list(itertools.permutations(horses))) [(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]

理解迭代的內部機制

迭代是一個暗含可迭代對象(實現了__iter__()方法)和迭代器(實現了__next__()方法)的過程。可迭代對象是任何你可以從中得到迭代器的對象。迭代器是可以讓你對可迭代對象進行迭代的對象。

更多信息請參考how does the for loop work。

轉載于:https://www.cnblogs.com/GuoYaxiang/p/6215685.html

總結

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

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