1 yield表達(dá)式的應(yīng)用
1.1 利用yield返回值給函數(shù)體的變量傳值
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
while True:
dish = yield None
print('%s 點(diǎn)了 %s' %(name, dish))
g=func('第一桌')
first_dish = next(g)
print(first_dish)
第一桌 準(zhǔn)備點(diǎn)菜
None # 利用yield傳值, 需要指定yield的返回值
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
while True:
dish = yield '鮑魚(yú)'
print('%s 點(diǎn)了 %s' %(name, dish))
g=func('第一桌')
first_dish = next(g)
print(first_dish)
第一桌 準(zhǔn)備點(diǎn)菜
鮑魚(yú)
1.2 yield表達(dá)式格式生成器
g.send() 給yield賦值, yield會(huì)將值轉(zhuǎn)給變量, 此時(shí)變量拿到的是yield從g.send()接收到的值
g.send() 相當(dāng)于執(zhí)行了next方法, 只不過(guò)具備了傳值功能, 如果單純的執(zhí)行next方法, 那么給變量傳的就是yield的返回值
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
while True:
dish = yield
print('%s 點(diǎn)了 %s' %(name, dish))
g=func('第一桌')
g.send(None) # 第一次執(zhí)行g(shù).send需要傳None來(lái)初始化生成器, 讓函數(shù)先掛起在yield,等待send傳值
g.send('土豆') # 之后每一次變量dish的值, 取決于通過(guò)g.send()給yield傳的值, 每執(zhí)行一次send, 會(huì)把值傳給變量, 然后打印print, 之后再回到y(tǒng)ield, 等著下一次send傳值
g.send('地瓜') # 第二次傳了土豆, 那么yield就會(huì)把土豆傳給dish, 之后在打印print
第一桌 準(zhǔn)備點(diǎn)菜
第一桌 點(diǎn)了 土豆
第一桌 點(diǎn)了 地瓜
通過(guò)g.close()結(jié)束傳值
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
while True:
dish = yield
print('%s 點(diǎn)了 %s' %(name, dish))
g=func('第一桌')
g.send(None)
g.send('土豆')
g.send('地瓜')
g.close()
g.send('肉')
g.send('肉')
StopIteration
第一桌 準(zhǔn)備點(diǎn)菜
第一桌 點(diǎn)了 土豆
第一桌 點(diǎn)了 地瓜
g.send()方法, 一次只能傳一個(gè)值, 但是可以傳容器類型
1.3 表達(dá)式綜合應(yīng)用
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
while True:
dish = yield 111
print('%s 點(diǎn)了 %s' %(name, dish))
g=func('第一桌') # 運(yùn)行函數(shù), 拿到生成器
res1 = g.send(None) # 首次執(zhí)行, 需要通過(guò)send(None)來(lái)初始化生成器, 讓函數(shù)掛起在yield,等待傳值, 之后每次通過(guò)send給yield傳值, 進(jìn)而給變量dish傳值, 每次傳值yield的返回值就是yield后的值
print(res1)
res2 = g.send('土豆')
print(res2)
res3 = g.send('地瓜')
print(res3)
第一桌 準(zhǔn)備點(diǎn)菜
111
第一桌 點(diǎn)了 土豆
111
第一桌 點(diǎn)了 地瓜
111
執(zhí)行順序
1. 執(zhí)行send方法,將參數(shù)傳給yield, 進(jìn)而傳給dish變量
2. 執(zhí)行print, 函數(shù)代碼結(jié)束, 返回while循環(huán), 然后將yield后的值返回
3. yield的返回值就看yield后跟了什么, yield拿到返回值后, 程序掛起在yield, 等待下一次send傳值
yield返回值是列表的情況
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
food_list = []
while True:
dish = yield food_list
print('%s 點(diǎn)了 %s' %(name, dish))
food_list.append(dish)
g=func('第一桌')
- 第一步, 執(zhí)行send(None), 初始化生成器, yield返回空列表,程序掛起在yield等待send傳值
res1 = g.send(None)
print(res1) # g.send()的返回值就是yield后的值
第一桌 準(zhǔn)備點(diǎn)菜
[]
- 第二次, send傳值'土豆'
1. yield從send拿到土豆, 然后傳給dish, 接著執(zhí)行print代碼
2. print代碼執(zhí)行完, 執(zhí)行列表追加, 將土豆追加到列表, 此時(shí)代碼執(zhí)行完, 返回循環(huán), 進(jìn)入yield
3. yield拿到返回值food_list列表, 因此打印res2, 會(huì)拿到y(tǒng)ield的新的返回值也就是追加后的列表
4. 程序掛起在yield, 等待下次send傳值
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
food_list = []
while True:
dish = yield food_list
print('%s 點(diǎn)了 %s' %(name, dish))
food_list.append(dish)
g=func('第一桌')
res1 = g.send(None)
print(res1)
res2 = g.send('土豆') #
print(res2)
- 第三次, send傳值'地瓜'
def func(name):
print('%s 準(zhǔn)備點(diǎn)菜' %(name))
food_list = []
while True:
dish = yield food_list
print('%s 點(diǎn)了 %s' %(name, dish))
food_list.append(dish)
g=func('第一桌')
res1 = g.send(None)
print(res1)
res2 = g.send('土豆')
print(res2)
res3 = g.send('地瓜')
print(res3)
第一桌 準(zhǔn)備點(diǎn)菜
[]
第一桌 點(diǎn)了 土豆
['土豆']
第一桌 點(diǎn)了 地瓜
['土豆', '地瓜']
2 三元表達(dá)式
可以簡(jiǎn)化利用條件判斷拿到返回值的需求
格式:
條件成立的返回值 if 條件判斷 else 條件不成立的返回值
正常情況根據(jù)條件拿到返回值
def max2(x,y):
if x > y:
return x
else:
return y
res = max2(1,2)
print(res)
2
利用三元表達(dá)式
x = 1
y = 2
res = 111 if x > y else 222
print(res)
222
函數(shù)內(nèi)使用三元表達(dá)式
def max2(x,y):
res = 111 if x > y else 222
print(res)
max2(1,2)
2
3 列表生成式
用精簡(jiǎn)的代碼生成新的列表
舉例: 將名字中以soccer結(jié)尾的元素提取到新的列表
play = ['david_soccer','owen_soccer','cluo_soccer','michael_basketball']
soccer_play = []
for name in play:
if name.endswith('soccer'):
soccer_play.append(name)
print(soccer_play)
['david_soccer', 'owen_soccer', 'cluo_soccer']
利用列表生成式
play = ['david_soccer','owen_soccer','cluo_soccer','michael_basketball']
soccer_play = [name for name in play if name.endswith('soccer')]
print(soccer_play)
列表生成式格式
新列表 = [如果條件成立就追加到列表的值 for 循環(huán) if 條件判斷]
新列表 = [如果條件成立就追加到列表的值 for 循環(huán)] # 可以不接if條件, 那默認(rèn)就是條件永遠(yuǎn)為T(mén)rue
新列表 = [任何值 for 循環(huán)] # 追加的值可以是任意值
案例: 把列表中所有小寫(xiě)字母, 變成大寫(xiě)字母
play = ['david_soccer','owen_soccer','cluo_soccer','michael_basketball']
new_play = [name.upper() for name in play]
print(new_play)
['DAVID_SOCCER', 'OWEN_SOCCER', 'CLUO_SOCCER', 'MICHAEL_BASKETBALL']
案例: 把列表中所有名字去掉_soccer后綴
play = ['david_soccer','owen_soccer','cluo_soccer','michael_basketball']
new_play = [name.replace('_soccer','') for name in play]
print(new_play)
['david', 'owen', 'cluo', 'michael_basketball']
4 字典生成式
案例1:
keys = ['name','age','job']
dict = {key:None for key in keys}
print(dict)
{'name': None, 'age': None, 'job': None}
案例2:
items = [('name','admin'),('age','20'),('gender','male')]
dict = {k:v for k,v in items if k != 'gender'} # 利用元組的解壓賦值, 判斷k是否不等于gender, 如果成立就加入到字典
print(dict)
5 集合生成式
案例:
keys = ['name','age','gender']
set = {key for key in keys}
print(set)
6 生成器表達(dá)式
綜合案例: 統(tǒng)計(jì)一個(gè)文本中的字符總個(gè)數(shù)
方法1: 代碼過(guò)長(zhǎng)
with open(r'user_info.txt', mode = 'rt', encoding='utf-8') as f:
sum = 0 # 初始化總個(gè)數(shù)為0
for i in f: # for循環(huán)一個(gè)文件, 每次取出文件的一行, 并且是字符
sum += len(i) # len(i)計(jì)算出每行的字符個(gè)數(shù), 追加給sum
print(sum)
方法2: 雖然代碼精簡(jiǎn), 但是一旦文件行數(shù)過(guò)多的情況下, 每次統(tǒng)計(jì)出來(lái)一行的字符個(gè)數(shù), 再追加到列表, 會(huì)造成列表元素過(guò)多, 占用內(nèi)存過(guò)大
with open(r'user_info.txt', mode = 'rt', encoding='utf-8') as f:
list = [len(i) for i in f ]
print(sum(list))
方法3: 利用生成器表達(dá)式, 效率最高
with open(r'user_info.txt', mode = 'rt', encoding='utf-8') as f:
res = sum((len(line) for line in f))
print(res)