Python關(guān)鍵字yield的使用場(chǎng)景及用法詳解
一、yield 的基本概念
在 Python 編程語(yǔ)言中,yield是一個(gè)至關(guān)重要的關(guān)鍵字,它用于定義生成器函數(shù)(generator function)。與普通函數(shù)使用return返回結(jié)果不同,生成器函數(shù)使用yield產(chǎn)生一個(gè)值,同時(shí)"凍結(jié)"函數(shù)的當(dāng)前狀態(tài),使得下次調(diào)用時(shí)可以從凍結(jié)點(diǎn)繼續(xù)執(zhí)行。
yield的出現(xiàn)使得 Python 能夠優(yōu)雅地實(shí)現(xiàn)惰性計(jì)算(lazy evaluation),這種特性在處理大數(shù)據(jù)集或無(wú)限序列時(shí)尤為有用。傳統(tǒng)函數(shù)在返回結(jié)果后會(huì)釋放所有資源并忘記之前的執(zhí)行狀態(tài),而生成器函數(shù)則能夠記住它的狀態(tài),在需要時(shí)繼續(xù)產(chǎn)生下一個(gè)值。
二、生成器函數(shù)與普通函數(shù)的區(qū)別
生成器函數(shù)與普通函數(shù)在定義上非常相似,唯一的區(qū)別在于前者使用yield而非return。但這種表面上的微小差異帶來(lái)了行為上的巨大不同:
- 執(zhí)行流程:普通函數(shù)從開始執(zhí)行到 return 語(yǔ)句后立即退出,而生成器函數(shù)在遇到 yield 時(shí)會(huì)暫停執(zhí)行,保存所有局部變量狀態(tài),等待下一次調(diào)用。
- 內(nèi)存使用:普通函數(shù)需要一次性計(jì)算所有結(jié)果并存儲(chǔ)在內(nèi)存中,生成器則是按需生成值,大大節(jié)省內(nèi)存空間。
- 返回值:普通函數(shù)返回一個(gè)具體的值或?qū)ο?,生成器函?shù)返回一個(gè)生成器對(duì)象,這個(gè)對(duì)象遵循迭代器協(xié)議。
例如,比較以下兩個(gè)函數(shù):
# 普通函數(shù)
def squares(n):
result = []
for i in range(n):
result.append(i*i)
return result
# 生成器函數(shù)
def squares_gen(n):
for i in range(n):
yield i*i
第一個(gè)函數(shù)會(huì)一次性生成所有平方數(shù)并存儲(chǔ)在列表中,而第二個(gè)函數(shù)則會(huì)在每次迭代時(shí)生成一個(gè)平方數(shù),內(nèi)存效率更高。
三、yield 的工作機(jī)制
理解yield的工作機(jī)制對(duì)于掌握生成器至關(guān)重要。當(dāng) Python 解釋器遇到包含yield語(yǔ)句的函數(shù)時(shí),它會(huì)將其特殊處理為一個(gè)生成器函數(shù)。調(diào)用生成器函數(shù)時(shí),不會(huì)立即執(zhí)行函數(shù)體,而是返回一個(gè)生成器對(duì)象。
生成器對(duì)象實(shí)現(xiàn)了迭代器協(xié)議,即包含__iter__()和__next__()方法。每次調(diào)用next()函數(shù)或在 for 循環(huán)中迭代時(shí),生成器函數(shù)會(huì)從上次暫停的位置繼續(xù)執(zhí)行,直到遇到下一個(gè)yield語(yǔ)句,此時(shí)yield后的表達(dá)式值會(huì)被返回給調(diào)用者,函數(shù)狀態(tài)再次被凍結(jié)。
當(dāng)函數(shù)執(zhí)行完畢(或遇到 return 語(yǔ)句)時(shí),生成器會(huì)拋出StopIteration異常,表示迭代結(jié)束。這個(gè)異常通常被 for 循環(huán)等迭代上下文自動(dòng)處理。
四、yield 的常見使用場(chǎng)景
- 處理大型數(shù)據(jù)集:當(dāng)需要處理的數(shù)據(jù)量太大而無(wú)法一次性裝入內(nèi)存時(shí),生成器可以逐項(xiàng)產(chǎn)生數(shù)據(jù),顯著降低內(nèi)存消耗。
def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f:
yield line.strip()
- 生成無(wú)限序列:生成器可以表示無(wú)限序列,如斐波那契數(shù)列、素?cái)?shù)序列等,因?yàn)橹凳前葱枭傻摹?/li>
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
- 實(shí)現(xiàn)管道:多個(gè)生成器可以串聯(lián)起來(lái)形成處理管道,每個(gè)生成器負(fù)責(zé)特定的處理步驟。
def filter_even(numbers):
for n in numbers:
if n % 2 == 0:
yield n
def square(numbers):
for n in numbers:
yield n ** 2
# 使用管道
numbers = range(100)
result = square(filter_even(numbers))
- 協(xié)程和狀態(tài)保持:生成器可以用于實(shí)現(xiàn)簡(jiǎn)單的協(xié)程,保持函數(shù)狀態(tài)并在不同時(shí)間點(diǎn)進(jìn)行交互。
五、yield 的高級(jí)用法
除了基本用法外,yield還有一些更高級(jí)的應(yīng)用:
- yield from:Python 3.3 引入的
yield from語(yǔ)法用于委托生成器,簡(jiǎn)化了生成器的嵌套使用。
def chain(*iterables):
for it in iterables:
yield from it
- 生成器表達(dá)式:類似于列表推導(dǎo)式,但使用圓括號(hào),返回一個(gè)生成器對(duì)象。
gen = (x*x for x in range(10)) # 生成器表達(dá)式
- 雙向通信:生成器可以通過(guò)
send()方法接收數(shù)據(jù),實(shí)現(xiàn)雙向通信。
def accumulator():
total = 0
while True:
value = yield total
if value is None:
break
total += value
六、性能考量
使用生成器可以帶來(lái)顯著的性能優(yōu)勢(shì),特別是在內(nèi)存使用方面。由于生成器是惰性求值的,它們:
- 減少內(nèi)存占用,不需要預(yù)先存儲(chǔ)所有結(jié)果
- 可以立即開始產(chǎn)生第一個(gè)值,而不必等待所有計(jì)算完成
- 適用于流式數(shù)據(jù)處理和實(shí)時(shí)系統(tǒng)
然而,生成器也有一些限制:
- 生成器只能迭代一次,要重復(fù)使用需要重新創(chuàng)建生成器
- 無(wú)法隨機(jī)訪問(wèn),只能順序訪問(wèn)
- 在某些情況下,如果所有數(shù)據(jù)確實(shí)需要同時(shí)存在,使用列表可能更直接
以上就是Python中關(guān)鍵字yield的使用場(chǎng)景及用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Python關(guān)鍵字yield的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用OpenCV對(duì)運(yùn)動(dòng)員的姿勢(shì)進(jìn)行檢測(cè)功能實(shí)現(xiàn)
2022年奧林匹克運(yùn)動(dòng)會(huì)如期舉行,以不正確的方式進(jìn)行運(yùn)動(dòng)風(fēng)險(xiǎn)在增加,人體姿勢(shì)估計(jì)是計(jì)算機(jī)視覺領(lǐng)域的重要問(wèn)題,接下來(lái)通過(guò)本文給大家介紹下使用OpenCV對(duì)運(yùn)動(dòng)員的姿勢(shì)進(jìn)行檢測(cè)功能,感興趣的朋友一起看看吧2022-02-02
Python入門必須知道的11個(gè)知識(shí)點(diǎn)
這篇文章主要為大家詳細(xì)介紹了Python入門必須知道的11個(gè)知識(shí)點(diǎn),幫助更好地了解python,感興趣的小伙伴們可以參考一下2018-03-03
點(diǎn)云地面點(diǎn)濾波(Cloth Simulation Filter, CSF)
這篇文章主要介紹了點(diǎn)云地面點(diǎn)濾波(Cloth Simulation Filter, CSF)“布料”濾波算法介紹,本文從基本思想到實(shí)現(xiàn)思路一步步給大家講解的非常詳細(xì),需要的朋友可以參考下2021-08-08
Python腳本實(shí)現(xiàn)自動(dòng)化處理Excel選擇題
本文介紹了一個(gè)自動(dòng)整理選擇題的Python腳本,可以將秒鐘自動(dòng)將雜亂的試題題題庫(kù)整理成Excel表格格式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-05-05
DjangoUeditor圖片不顯示img的src沒有域名問(wèn)題
在使用DjangoUeditor過(guò)程中,可能遇到圖片上傳后不顯示問(wèn)題,解決辦法是修改源碼view.py,加入代碼使得保存的圖片URL帶有協(xié)議和域名,具體做法是在保存圖片代碼中添加request.scheme獲取協(xié)議,request.META['HTTP_HOST']獲取域名2024-09-09
Python腳本實(shí)現(xiàn)DNSPod DNS動(dòng)態(tài)解析域名
這篇文章主要介紹了Python腳本實(shí)現(xiàn)DNSPod DNS動(dòng)態(tài)解析域名,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-02-02

