1. 程式人生 > >2018.8.13 python中生成器和生成器表達式

2018.8.13 python中生成器和生成器表達式

推導式 程序 列表推導式 strong 雞蛋 inf result 繼續 人的

主要內容:

1、生成器和生成器函數

2、列表推導式

一、生成器

生成器是指就是叠代器,在python中有三種方式來獲取生成器:

1、通過生成器函數

2、通過各種推導式來實現生成器

3、通過數據的轉換也可以獲取生成器

技術分享圖片

yield 和return的區別:

yield分段來執行一個函數,break停止函數執行。

技術分享圖片

當程序運行完最後一個yield,那麽後面繼續進行__next__()程序會報錯。

send使用方法:send和__next__()一樣可以讓生成器執行到下一個yield。

def eat():
    print(我吃什麽啊)
    a = yield 饅頭
    print(a = ,a)
    b = yield 大餅
    print(b = ,b)
    c = yield 韭菜盒子
    print(c = ,c)
    yield GAME OVER
gen = eat()   #獲取生成器
ret1 = gen.__next__()
print(ret1)     #結果:我吃什麽啊   饅頭
ret2 = gen.send(胡辣湯)
print(ret2)      #結果:a =  胡辣湯    大餅
ret3 = gen.send(狗糧) print(ret3) #結果:b = 狗糧 韭菜盒子 ret4 = gen.send(貓糧) print(ret4) #結果:c = 貓糧 GAME OVER

send 和 __next__()區別:

1、send和 __next__()都是讓生成器向下走一次

2、send可以給上一個yield的位置傳遞值,不能給最後一個yield發送值。在第一次執行生成器的時候不能使用send()。

生成器可以使用for循環來獲取內部元素:

def func():
    print(111)
    
yield 222 print(333) yield 444 print(555) yield 666 gen = func() for i in gen: print(i) # 結果: # 111 # 222 # 333 # 444 # 555 # 666 for i in list(gen): print(i) # 結果: # 111 # 222 # 333 # 444 # 555 # 666

二、列表推導式,生成器表達式及其他推導式

首先我們先看一下這樣的代碼, 給出一個列表, 通過循環, 向列表中添加1-14 :

lst = []
for i in range(1, 15):
lst.append(i)
print(lst)

替換成列表推導式:

lst = [i for i in range(1, 15)]
print(lst)

列表推導式的常用寫法:

[ 結果 for 變量 in 可叠代對象 if 條件 ]

生成器表達式和列表推導式的語法基本上是一樣的. 只是把[ ]替換成()

# 獲取1-100內能被3整除的數
gen = (i for i in range(1,100) if i % 3 == 0)
for num in gen:
print(num)
# 100以內能被3整除的數的平方
gen = (i * i for i in range(100) if i % 3 == 0)
for num in gen:
print(num)
# 尋找名字中帶有兩個e的人的名字
names = [[Tom, Billy, Jefferson, Andrew, Wesley, Steven,
Joe],
[Alice, Jill, Ana, Wendy, Jennifer, Sherry, Eva]]
# 不?推導式和表達式
result = []
for first in names:
for name in first:
if name.count("e") >= 2:
result.append(name)
print(result)
# 推導式
gen = (name for first in names for name in first if name.count("e") >= 2)
for name in gen:
print(name)

生成器表達式和列表推導式的區別:
1. 列表推導式比較耗內存. 一次性加載. 生成器表達式幾乎不占用內存. 使用的時候才分配和使用內存。
2. 得到的值不一樣. 列表推導式得到的是一個列表. 生成器表達式獲取的是一個生成器。
舉個栗子:
同樣一籃子雞蛋. 列表推導式: 直接拿到一籃子雞蛋. 生成器表達式: 拿到一個老母雞. 需要雞蛋就給你下雞蛋。

def func():
    print(111)
    yield 222
    print(333)
    yield 444
    print(555)
g = func()    #生成器g
g1 = (i for i in g)   #生成器g1,但是g1的數據來源於g
g2 = (i for i in g1)  #生成器g2,來源g1
print(list(g))   #獲取g中的數據,這時func()才會被執行,結果為:111 333 555 [222,444]
print(list(g1))#獲取g1中的數據,g1的數據來源於g,但是g已經取完了,g1也就沒有數據,結果為[]
print(list(g2))#和g1同理,結果為[]

深坑----生成器,要值得時候才拿值。

字典推導式:

# 把字典中的key和value互換
dic = {a: 1, b: 2}
new_dic = {dic[key]: key for key in dic}
print(new_dic)
# 在以下list中. 從lst1中獲取的數據和lst2中相對應的位置的數據組成?個新字典
lst1 = [jay, jj, sylar]
lst2 = [周傑倫, 林俊傑, 邱彥濤]
dic = {lst1[i]: lst2[i] for i in range(len(lst1))}
print(dic)

集合推導式:

lst = [1, -1, 8, -8, 12]
# 絕對值去重
s = {abs(i) for i in lst}
print(s)

總結: 推導式有, 列表推導式, 字典推導式, 集合推導式, 沒有元組推導式
生成器表達式: (結果 for 變量 in 可叠代對象 if 條件篩選)
生成器表達式可以直接獲取到生成器對象. 生成器對象可以直接進行for循環. 生成器具有惰性機制。

def add(a,b):
    return a+b
def test():
    for r_i in range(4):
        yield r_i
g = test()
for n in [2,10]:
    g = (add(n,i) for i in g)
print(list(g))

# 結果:[20, 21, 22, 23]

2018.8.13 python中生成器和生成器表達式