2018.8.13 python中生成器和生成器表達式
主要內容:
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中生成器和生成器表達式