生成器

生成器


??什么是生成器?提到生成器,往往離不開另一個概念:迭代器,我們知道的迭代器有兩種:一種是調(diào)用方法直接返回的,一種是可迭代對象通過執(zhí)行iter方法得到的,迭代器有的好處是可以節(jié)省內(nèi)存。如果在某些情況下,我們也需要節(jié)省內(nèi)存,就只能自己寫。我們自己用python寫的能實(shí)現(xiàn)迭代器功能的東西就叫生成器。 生成器分為兩種:

  • 生成器函數(shù):常規(guī)函數(shù)定義,但是,使用yield語句而不是return語句返回結(jié)果。yield語句一次返回一個結(jié)果,在每個結(jié)果中間,掛起函數(shù)的狀態(tài),以便下次重它離開的地方繼續(xù)執(zhí)行
  • 生成器表達(dá)式:類似于列表推導(dǎo),但是,生成器返回按需產(chǎn)生結(jié)果的一個對象,而不是一次構(gòu)建一個結(jié)果列表

生成器函數(shù)


??一個包含yield關(guān)鍵字的函數(shù)就是一個生成器函數(shù)。yield可以為我們從函數(shù)中返回值,但是yield又不同于return,return的執(zhí)行意味著程序的結(jié)束,調(diào)用生成器函數(shù)不會得到返回的具體的值,而是得到一個可迭代的對象。每一次獲取這個可迭代對象的值,就能推動函數(shù)的執(zhí)行,獲取新的返回值。直到函數(shù)執(zhí)行結(jié)束。見下:

def func(x):            #定義一個函數(shù),計(jì)算給定數(shù)階乘
    for i in range(x):         
        yield i * i     #有yield利用yield關(guān)鍵字返回結(jié)果,每次只返回一個

for j in func(5):
    print(j)
0
1
4
9
16

同樣使用普通函數(shù)來實(shí)現(xiàn)上述功能,會明顯發(fā)現(xiàn)生成器函數(shù)代碼少于普通函數(shù)。最為關(guān)鍵的是生成器函數(shù)要更節(jié)省內(nèi)存

def func1(x):
    li = []
    for i in range(x):
        li.append(i)
for j in func(5):
    print(j)
0
1
4
9
16

next和send關(guān)鍵

??由于生成器函數(shù)本質(zhì)上是迭代器,所以生成器的接收參數(shù)也是借助next關(guān)鍵字實(shí)現(xiàn)。但同時,生成器函數(shù)還有一個send關(guān)鍵字同樣可以接收參數(shù),那么二者有什么區(qū)別呢?

def func1():
    count = yield 6
    print(count)
    count1 = yield 7
    print(count1)
    yield 8

g = func1()
print(next(g))
print(g.__next__())
print(g.send('太白'))
6
None
7
太白
8

send 獲取下一個值的效果和next基本一致,只是在獲取下一個值的時候,給上一yield的位置傳遞一個數(shù)據(jù)。

使用send的注意事項(xiàng)

  • 第一次使用生成器的時候 是用next獲取下一個值
  • 最后一個yield不能接受外部的值

列表推導(dǎo)式與生成器表達(dá)式


??列表推導(dǎo)式是生成滿足一定規(guī)律的列表的簡單方式,其只需一行代碼便可生成一個較為復(fù)雜的列表,在節(jié)省代碼方面大有可為。以下用代碼來詳細(xì)解釋:

# 需求:要求生成一個存放1-30以內(nèi)所有能被3整除的列表。按照原來的方法會是這樣:
li = []
for i in range(1,31):
    if i % 3 == 0:
        li.append(i)
print(li)
#而有了列表推導(dǎo)式后,此代碼可以被省略為一行:
print([i for i in range(1,31) if i % 3 == 0])
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

列表推導(dǎo)式通??梢苑譃閮煞N:

  • 循環(huán)模式:[變量(加工后的變量) for 變量 in iterable]
  • 篩選模式:[變量(加工后的變量) for 變量 in iterable if 條件]
#循環(huán)模式
#1到10中每個數(shù)的平方b
[i*i for i in range(1,12)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121]
#篩選模式
#找到嵌套列表中名字含有兩個‘e’的所有名字

names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
[i for x in names for i in x if i.count('e') == 2 ]
['Jefferson', 'Wesley', 'Steven', 'Jennifer']

列表生成器


  1. 把列表解析的[]換成()得到的就是生成器表達(dá)式

  2. 列表解析與生成器表達(dá)式都是一種便利的編程方式,只不過生成器表達(dá)式更節(jié)省內(nèi)存

  3. Python不但使用迭代器協(xié)議,讓for循環(huán)變得更加通用。大部分內(nèi)置函數(shù),也是使用迭代器協(xié)議訪問對象的。

sum(x ** 2 for x in range(4))
14
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容