<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們學習完推導式之後發現,推導式就是在容器中使用一個for迴圈而已,為什麼沒有元組推導式?
原因就是“元組推導式”的名字不是這樣的,而是叫做生成器表示式。
生成器表示式本質上就是一個迭代器,是定義迭代器的一種方式,是允許自定義邏輯的迭代器。生成器使用generator表示。
迭代器本身是系統內建的, 無法重寫內建的邏輯結構;而生成器是使用者自定義的,可以重寫邏輯結構。所以生成器就是一個迭代器,只是我們將自己寫的迭代器叫做生成器作為區分而已。
生成器有兩種建立方式
1.生成器表示式,就是“元組推導式”
3.生成器函數,就是使用def定義,裡面使用yield
關鍵字
from collections import Iterator, Iterable # 生成器表示式(元組推導式) gen = (i * 2 for i in range(1, 11)) print(isinstance(gen, Iterable)) # 判斷是否是迭代物件 print(isinstance(gen, Iterator)) # 判斷是否是迭代器 # 這個 gen 就是生成器
我們上面說到,生成器函數如何定義?其實和普通的函數定義的方法是一樣的,都是要使用def
關鍵字來定義,其它的寫法沒有任何要求,普通函數怎麼寫生成器函數就怎麼寫,唯一的要求就是要使用yield
關鍵字。
要注意,生成器函數就是一個函數,是使用了yield的函數,只不過生成器函數是用來定義生成器的。
yield
這個關鍵字其實類似於return
關鍵字,return
關鍵字的作用是在函數中使用,用來返回資料,yield
關鍵字的作用也是一樣的,就是用來返回資料,但是和return
還有其它的不同之處。
共同點
執行到對應語句的時候,就會返回對應的值。
不同點
return
執行的時候,函數就跳出,然後return
之後的所有作用域語句就會全部跳出,當函數再次呼叫的時候,整個函數就重新執行。
yield
執行的時候,返回資料,但是函數就會記住跳出的位置,當你再次呼叫函數(生成器)的時候,就從上一次跳出的地方繼續執行,是不是和迭代器的取值有異曲同工之處?
yield的使用方法有兩種,一種是和return的使用方法一樣,在關鍵字的後面直接新增返回值,這是推薦使用的方法;
第二種方法使用將yield作為一個函數使用,就是在yield後面使用括號,在括號中填寫返回的值。
# 1、定義一個生成器函數 # 生成器函數就是一個使用yield的函數 def myGen(): print(1) yield 11 print(2) yield 22 print(3) yield 33 # 2、初始化生成器 # 執行生成器函數,返回一個物件,就是生成器物件,簡稱生成器 from collections import Iterator gen = myGen() res = isinstance(gen, Iterator) print(res) # True 返回True說明生成器本質上就是一個迭代器 # 3、呼叫生成器 # 生成器本質上就是一個迭代器,還記得迭代器如何呼叫嗎? res = next(gen) print(res) """ 結果: 1 (生成器函數中的語句 print(1)) 11 (yield返回的值,print(res)) """
send
和next
一樣,都是用來取出迭代器中的值的函數,send
是生成器的內建函數。而且send和next相比,功能更加的強大,next只能取值;send不但能取值,而且還能傳送值。
範例
定義生成器函數
def myGen(): print('process start') # res獲取yield的值 res = yield 100 print(res, '內部列印1') print('process start') res = yield 200 print(res, '內部列印2') print('process start') res = yield 300 print(res, '內部列印3')
初始化生成器
gen = myGen()
第一次呼叫生成器
# 在使用send時,第一次傳遞的資料必須是None,這是硬性語法,以為send第一次傳遞引數的時候,還沒有遇到yield,所以不能傳送。 res = gen.send(None) print(res) """ 結果: process start 100 """
使用send第一次呼叫生成器的時候執行了下面的語句:
print('process start') res = yield 100
執行到yield 100的時候,才碰到了yield,但是send之前沒有遇到過yield,所以不能傳入任何值,None沒有任何意義,這是硬性語法。
這裡注意,res = yield 100
中的res此時沒有任何價值。因為這個一條語句我們目前只執行了一半,執行了yield 100
,還有res的賦值沒有完成,所以現在的res沒有任何的意義。
第一次呼叫生成器,返回100,這個100則是語句res = yield 100
返回的值。
第二次呼叫
res = next(gen) print(res) """ 結果: None 內部列印1 process start 200 """
第二次呼叫執行了以下語句:
res = yield 100 print(res, '內部列印1') print('process start') res = yield 200
注意,生成器函數在呼叫的時候,會從上一次yield返回值的地方,就是res = yield 100
,但是這個語句第二次呼叫的時候,只會執行一半,因為另一半在第一次呼叫的時候已經執行完了,就是yield 100
,就是說還有res的賦值沒有進行,但是第二次呼叫使用的是next,next沒有傳送值的能力,所以res就沒有賦予任何值,,在列印的時候,res就是一個None。
第三次呼叫
res = gen.send('第三次呼叫') print(res) """ 結果: 第三次呼叫 內部列印2 process start 300 """
第三次呼叫執行的語句是:
res = yield 200 print(res, '內部列印2') print('process start') res = yield 300
這次和第二次的呼叫基本是一樣的,但是這次是使用send呼叫,所以傳送了值過去,執行於是將值賦予了res。
第四次呼叫
res = gen.send(None) print(res) """ 結果: None 內部列印3 StopIteration (報錯) """
第四次呼叫,執行以下語句:
res = yield 300 print(res, '內部列印3')
第四次呼叫生成器,沒有可以執行的yield語句,所以返回不了任何資料,因此報出了 StopIteration
的錯誤。
現在我們就已經學習完了容器和迭代器、生成器的相關知識,我們也知道了可迭代物件和迭代器的區別,那麼現在我們要說的是,如果我們需要制定一個容器供我們遍歷使用,那麼我們優先使用迭代器而不是容器這樣的一個普通的可迭代物件。
在我們之後的日常使用過程當中,我們有時就會發現,我們需要在一個迴圈中遍歷一個容器供我們使用,但是這個容器中的值非常多,使這個容器佔據的記憶體空間非常大,消耗了大量的資源,導致我們的程式非常慢。這個時候我們就需要使用迭代器或者生成器去遍歷,迭代器每次遍歷只佔據當次遍歷時的記憶體空間,因此非常的節省資源,所以這就是我們優先使用迭代器的理由。
現在我們就學習完了python中的所有的函數型別,知道了python中的有內建函數、自定義函數,之後我們還會學習一些python的常用標準庫和第三方庫,裡面也有一些我們經常用到的函數。
以上就是一文詳解Python中生成器的原理與使用的詳細內容,更多關於Python生成器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45