python生成器 图片分类_Python内置类型(6)——生成器
上節(jié)內(nèi)容說到Python的for語句循環(huán)本質(zhì)上就是通過調(diào)用Iterable可迭代對象的__iter()__方法獲得一個Iterator迭代器對象,然后不斷調(diào)用Iterator迭代器對象__next()__方法實現(xiàn)的。Iterator迭代器對象則是一個需要實現(xiàn)__iter__()和__next__()兩個迭代器協(xié)議方法的對象。python中生成器提供了一種方便的方法來實現(xiàn)迭代器協(xié)議,而不需要必須實現(xiàn)__iter__()和__next__()兩個迭代器協(xié)議方法。
生成器的定義方式有兩種,一種是調(diào)用生成器函數(shù),一種是使用生成器表達式語法。
調(diào)用生成器函數(shù)
生成器函數(shù)是指在函數(shù)體中使用yield表達式僅返回結(jié)果的函數(shù)。yield表達式僅在定義生成器函數(shù)時使用,因此只能用在函數(shù)定義的主體中。在函數(shù)體中使用yield表達式會使該函數(shù)成為生成器函數(shù)。當生成器函數(shù)被調(diào)用時,它返回一個稱為生成器的迭代器,該迭代器由python自動生成。然后,生成器控制了生成器函數(shù)的執(zhí)行。因為返回的生成器是一個迭代器,所以生成器函數(shù)的執(zhí)行結(jié)果也就可以被循環(huán)。當生成器的的__next__方法被調(diào)用時,生成器函數(shù)的函數(shù)體內(nèi)的語句開始執(zhí)行,執(zhí)行進行到第一個yield表達式時,立即將yield表達式的結(jié)果返回給生成器的調(diào)用者,同時將生成器函數(shù)內(nèi)部的狀態(tài)掛起。即保持生成器函數(shù)的執(zhí)行進度,和生成器函數(shù)內(nèi)的局部狀態(tài):包括局部變量的當前綁定,指令指針,內(nèi)部計算棧和任何異常處理的狀態(tài)。當生成器的再次調(diào)用__next__方法來時,生成器函數(shù)恢復(fù)執(zhí)行,并再次執(zhí)行到y(tǒng)ield表達式返回結(jié)果再保持狀態(tài),直到無法再執(zhí)行到y(tǒng)ield表達式。此時生成器自動拋出StopIteration異常。
我們先定義一個簡單生成器函數(shù),函數(shù)功能返回數(shù)字0-9的平方數(shù)
# 生成器函數(shù),功能返回數(shù)字0-9的平方數(shù)
>>> def squares():
for i in range(10):
yield i**2
# 使用return關(guān)鍵字是普通函數(shù),使用yield關(guān)鍵字函數(shù)變成了生成器函數(shù)
使用參數(shù)g接收調(diào)用生成器函數(shù)squares的結(jié)果,然后分別在shell查看squares和g這兩個變量的類型
>>> g = squares()
#查看squares對象類型
>>> squares
#查看g對象類型
>>> g
從上面可以看出變量squares是函數(shù)類型,變量g是generator類型對象,generator從字面的理解上就是生成器類型。根據(jù)上一節(jié)迭代器中提到的知識,從collection模塊引入Iterator的抽象基類,驗證下generator類型是不是上面說的迭代器類型。
>>> from collections import Iterator
>>> isinstance(g,Iterator)
True
驗證成功,說明生成器函數(shù)的執(zhí)行結(jié)果確實是生成器,一種特殊的迭代器。
>>> for i in g:
print (i)
0
1
4
9
16
25
36
49
64
81
生成器表達式
除了使用生成器函數(shù)可以得到生成器,還可以生成器表達式得到生成器表達式。生成器表達式本身看起來像列表推到, 但不是用方括號而是用圓括號包圍起來:
>>> g2 = (x**2 for x in range(10))
>>> g2
at 0x0359AFC0>
>>> t = (1,2,3,4,5)
>>> g3 = (x**2 for x in t)
>>> g3
at 0x007F6180>
驗證:
>>> isinstance(g2,Iterator)
True
>>> isinstance(g3,Iterator)
True
使用:
>>> for i in g2:
print(i)
0
1
4
9
16
25
36
49
64
81
>>> for i in g3:
print(i)
1
4
9
16
25
和普通迭代器相比,生成器不單簡化了迭代器的定義,還在使用效率上有提升。因為生成器在循環(huán)時,生成器函數(shù)每次只會返回一個結(jié)果,然后保持內(nèi)部狀態(tài),所以生成器占用的內(nèi)存是很小的。以下兩個測試結(jié)果,第一個直接拋出MemoryError異常,第二個只能正確計算出結(jié)果。
# 全部數(shù)據(jù)先加載在1個列表上面,內(nèi)存占用高
>>> s1 = sum([i for i in range(100000000)])
Traceback (most recent call last):
File "", line 1, in
s1 = sum([i for i in range(100000000)])
File "", line 1, in
s1 = sum([i for i in range(100000000)])
MemoryError
# 數(shù)據(jù)幾乎不占內(nèi)存
>>> s2 = sum((i for i in range(100000000)))
>>> s2
4999999950000000
總結(jié)
以上是生活随笔為你收集整理的python生成器 图片分类_Python内置类型(6)——生成器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java get null_java 获
- 下一篇: websocket 发送图片_基于Web