15. Python之yield表達(dá)式和生成式

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('第一桌')
  1. 第一步, 執(zhí)行send(None), 初始化生成器, yield返回空列表,程序掛起在yield等待send傳值
res1 = g.send(None)
print(res1) # g.send()的返回值就是yield后的值
第一桌 準(zhǔn)備點(diǎn)菜
[]
  1. 第二次, 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)
  1. 第三次, 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)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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