欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python中yield函數(shù)的用法詳解

 更新時間:2025年03月13日 10:52:33   作者:大神神奇奇奇  
這篇文章詳細(xì)介紹了Python中的yield關(guān)鍵字及其用法,yield關(guān)鍵字用于生成器函數(shù)中,使得函數(shù)可以像迭代器一樣工作,但不會一次性將所有結(jié)果加載到內(nèi)存中,文中將用法介紹的非常詳細(xì),需要的朋友可以參考下

python官方api地址

1. yield介紹

在Python中,yield關(guān)鍵字主要用于生成器函數(shù)(generator functions)中,其目的是使函數(shù)能夠像迭代器一樣工作,即可以被遍歷,但不會一次性將所有結(jié)果都加載到內(nèi)存中。

2.yield基本用法

  • 定義生成器函數(shù)
def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()
print(next(gen))  # 輸出: 1
print(next(gen))  # 輸出: 2
print(next(gen))  # 輸出: 3
  • 使用 for 循環(huán)遍歷生成器生成器對象是可迭代的,因此可以使用 for 循環(huán)來遍歷生成器生成的值。
    下面例子中,for 循環(huán)遍歷生成器函數(shù)生成的所有值,并依次打印它們。
def simple_generator():
    yield 1
    yield 2
    yield 3

for value in simple_generator():
    print(value)
  • 生成器表達(dá)式下面例子中,生成器表達(dá)式生成了一個平方數(shù)序列,并使用 for 循環(huán)打印所有值。
gen_expr = (x * x for x in range(5))
for value in gen_expr:
    print(value)
  • 生成器轉(zhuǎn)列表
def simple_generator():
    yield 1
    yield 2
    yield 3
gen = simple_generator()
print(list(gen))  # 輸出: [1, 2, 3]

3.yield高級用法

3.1 yield send() 方法

生成器不僅可以通過 yield 返回值,還可以通過 send() 方法接收外部輸入。

send() 方法允許向生成器發(fā)送一個值,這個值將成為上一個 yield 表達(dá)式的值。

這種方式可以實現(xiàn)生成器與外部之間的雙向通信。

def coroutine():
    while True:
        received = yield
        print(f"接收到的數(shù)據(jù): {received}")

co = coroutine()
next(co)  # 預(yù)激生成器
co.send(10)  # 輸出: 接收到的數(shù)據(jù): 10
co.send(20)  # 輸出: 接收到的數(shù)據(jù): 20

在這個例子中,coroutine 生成器函數(shù)在每次迭代時接收外部數(shù)據(jù)并打印它。
next(co) 用于預(yù)激生成器,使其準(zhǔn)備好接收數(shù)據(jù)。

3.2 yield from方法

從Python 3.3開始,引入了 yield from 語法,它允許一個生成器委托另一個生成器來生成值。

這種委托機(jī)制可以簡化嵌套生成器的使用,提高代碼的可讀性和效率。

def base_code_pool():
    for i in range(3):
        yield f'BASE-{i + 1}'

def outsource_pool():
    for i in range(30):
        yield f'OUTS-{i + 1}'

def team_member_code():
    yield from base_code_pool()
    print('內(nèi)部資源編號用完,開始使用外包')
    yield from outsource_pool()

team_member = team_member_code()
for i in range(5):
    print(next(team_member))

運行結(jié)果:

BASE-1
BASE-2
BASE-3
內(nèi)部資源編號用完,開始使用外包
OUTS-1
OUTS-2

在這個例子中,team_member_code 生成器函數(shù)委托 base_code_pool 和 outsource_pool 生成器來生成值。
當(dāng) base_code_pool 的值用完后,生成器會繼續(xù)從 outsource_pool 生成值。

3.3 yield 和yield from疊加

yield 和 yield from 是 Python 中用于創(chuàng)建生成器的兩種方式,它們允許函數(shù)在迭代過程中逐步返回值,而不是一次性返回所有結(jié)果。
這種特性使得生成器非常適合處理大型數(shù)據(jù)集或無窮序列等場景,因為它們不會一次性將所有數(shù)據(jù)加載到內(nèi)存中,從而節(jié)省了內(nèi)存資源。

關(guān)于是否可以“疊加”yield 和 yield from 的結(jié)果,實際上我們討論的是如何組合多個生成器或者將一個生成器的結(jié)果傳遞給另一個生成器。

  • 使用 yield 和 yield from 組合生成器當(dāng)你想要組合兩個或更多個生成器時,你可以使用 yield 來逐個產(chǎn)出每個生成器中的元素,或者使用 yield from 來直接委托給子生成器,讓其負(fù)責(zé)產(chǎn)出自己的元素。
  • 例如:
def generator_a():
    for i in range(3):
        yield i

def generator_b():
    for i in range(3, 6):
        yield i

def combined_generators():
    # 使用 yield 直接產(chǎn)出每個生成器中的元素
    for value in generator_a():
        yield value
    for value in generator_b():
        yield value
    
    # 或者使用 yield from 委托給子生成器
    yield from generator_a()
    yield from generator_b()

在這個例子中,combined_generators 函數(shù)通過 yield 和 yield from 將兩個生成器的結(jié)果進(jìn)行了“疊加”。

這里,“疊加”的含義是指順序地連接了兩個生成器產(chǎn)生的輸出流,而不是數(shù)學(xué)意義上的加法操作。

可以將 yield 和 yield from 結(jié)合使用來實現(xiàn)生成器之間的組合,甚至可以在同一個函數(shù)內(nèi)部同時使用這兩種語句。

這樣做不僅可以簡化代碼結(jié)構(gòu),還能更靈活地控制生成器的行為。

讓我們深入探討一下如何有效地結(jié)合使用 yield 和 yield from 來“疊加”多個生成器的結(jié)果。

  • 結(jié)果的實際疊加如果我們談?wù)摰氖菍嶋H的結(jié)果疊加(如數(shù)值相加),那么你需要明確地編寫邏輯來實現(xiàn)這一點。
    比如,如果你想把來自不同生成器的數(shù)值相加以獲得總和,你可以這樣做:
def sum_of_generators(gen1, gen2):
    return sum(gen1) + sum(gen2)

total = sum_of_generators(generator_a(), generator_b())
print(total)  # 輸出: 15 (0+1+2+3+4+5)
# 輸出: 0 1 2 3 4 5
for item in combined_generators():
    print(item)

在這里,sum_of_generators 函數(shù)接收兩個生成器作為參數(shù),并分別對它們求和后再相加。
請注意,這種方法會立即消耗掉這兩個生成器的所有元素并計算出總和,這可能不是最有效的做法,特別是對于非常大的數(shù)據(jù)集。

  • 組合使用 yield 和 yield from上面的例子可以將 yield 和 yield from 結(jié)合使用來實現(xiàn)生成器之間的組合,甚至可以在同一個函數(shù)內(nèi)部同時使用這兩種語句。
    這樣做不僅可以簡化代碼結(jié)構(gòu),還能更靈活地控制生成器的行為。
    讓我們深入探討一下如何有效地結(jié)合使用 yield 和 yield from 來“疊加”多個生成器的結(jié)果。
    考慮一個場景,你有一個主生成器,它需要從多個子生成器中獲取值,并且自身也可能產(chǎn)生一些額外的值。
    在這種情況下,你可以用 yield 來直接產(chǎn)出這些額外的值,而用 yield from 來委派給子生成器。
    例如:
def generator_a():
    for i in range(3):
        yield i

def generator_b():
    for i in range(3, 6):
        yield i

def combined_generators():
    # 直接使用 yield 產(chǎn)出額外的值
    yield "Start"
    
    # 使用 yield from 委托給子生成器 a
    yield from generator_a()
    
    # 再次直接使用 yield 產(chǎn)出中間的值
    yield "Middle"
    
    # 使用 yield from 委托給子生成器 b
    yield from generator_b()
    
    # 最后直接使用 yield 產(chǎn)出結(jié)束的值
    yield "End"

# 輸出: Start 0 1 2 Middle 3 4 5 End
for item in combined_generators():
    print(item)

在這個例子中,combined_generators 函數(shù)展示了如何在同一個生成器內(nèi)混合使用 yield 和 yield from。

首先,它通過 yield 發(fā)出了字符串 "Start";

然后,利用 yield from 將控制權(quán)交給 generator_a(),后者負(fù)責(zé)產(chǎn)出 0, 1, 和 2

接著,再次使用 yield 發(fā)出 "Middle";之后,又通過 yield from 讓 generator_b() 產(chǎn)出 3, 4, 和 5

最后,以同樣的方式發(fā)出字符串 "End"。

這種方式允許你在不破壞原有邏輯的基礎(chǔ)上輕松添加新的生成邏輯,同時也保持了代碼的清晰度和可讀性。

處理復(fù)雜情況下的疊加

如果你面對的是更加復(fù)雜的場景,比如你需要對來自不同生成器的數(shù)據(jù)進(jìn)行某種形式的處理后再輸出,或者你需要根據(jù)某些條件決定是否調(diào)用某個子生成器,那么你可以繼續(xù)擴(kuò)展這種模式。

例如,假設(shè)你想把兩個生成器的結(jié)果相加后作為最終輸出的一部分:

def add_generators(gen1, gen2):
    iterator1 = iter(gen1)
    iterator2 = iter(gen2)
    try:
        while True:
            value1 = next(iterator1)
            value2 = next(iterator2)
            yield value1 + value2
    except StopIteration:
        pass

def enhanced_combined_generators():
    yield "Start"
    yield from add_generators(generator_a(), generator_b())
    yield "End"

# 輸出: Start 3 5 7 End
for item in enhanced_combined_generators():
    print(item)

綜上所述,yield 和 yield from 的結(jié)果可以通過編程邏輯被“疊加”,但這取決于你想要實現(xiàn)的具體行為。

如果是簡單的迭代輸出,則可以直接使用 yield from 來簡化代碼;

而如果是數(shù)值或其他類型的累加,則需要額外的邏輯來完成這個過程。

4.yield主要應(yīng)用場景

  • 處理大數(shù)據(jù)集生成器非常適合處理大數(shù)據(jù)集,因為它可以在需要時按需生成值,而不是一次性將所有值加載到內(nèi)存中。
    這可以顯著減少內(nèi)存使用,提高程序的性能。
def read_large_file(file_path):
    with open(file_path, 'r') as file:
        for line in file:
            yield line

for line in read_large_file('large_file.txt'):
    print(line, end='')

在這個例子中,生成器函數(shù) read_large_file 逐行讀取大文件,并使用 for 循環(huán)打印每行內(nèi)容。
這種方法避免了將整個文件加載到內(nèi)存中,從而節(jié)省了內(nèi)存。

  • 實現(xiàn)協(xié)程和并發(fā)生成器可以用于實現(xiàn)協(xié)程和并發(fā)編程模式。
    協(xié)程是一種用戶態(tài)的輕量級線程,可以用來模擬異步操作,實現(xiàn)非阻塞的I/O處理等。
def coroutine_example():
    while True:
        received = yield
        print(f"處理數(shù)據(jù): {received}")

co = coroutine_example()
next(co)  # 預(yù)激生成器
co.send('data1')  # 輸出: 處理數(shù)據(jù): data1
co.send('data2')  # 輸出: 處理數(shù)據(jù): data2

在這個例子中, coroutine_example 生成器函數(shù)可以接收外部數(shù)據(jù)并處理它,實現(xiàn)了簡單的協(xié)程功能。

  • 數(shù)據(jù)處理管道生成器可以用于實現(xiàn)數(shù)據(jù)處理管道,每個生成器函數(shù)負(fù)責(zé)一個處理步驟。
    這種模式可以將復(fù)雜的任務(wù)分解為多個簡單的步驟,提高代碼的可讀性和可維護(hù)性。
def pipeline_stage1(data):
    for item in data:
        yield item * 2

def pipeline_stage2(data):
    for item in data:
        yield item + 1

data = range(5)
stage1 = pipeline_stage1(data)
stage2 = pipeline_stage2(stage1)

for value in stage2:
    print(value)

在這個例子中,數(shù)據(jù)經(jīng)過兩個生成器函數(shù)處理。

首先在 pipeline_stage1 中乘以2,然后在 pipeline_stage2 中加1。

def add_generators(gen1, gen2):
    iterator1 = iter(gen1)
    iterator2 = iter(gen2)
    try:
        while True:
            value1 = next(iterator1)
            value2 = next(iterator2)
            yield value1 + value2
    except StopIteration:
        pass

def enhanced_combined_generators():
    yield "Start"
    yield from add_generators(generator_a(), generator_b())
    yield "End"
# 輸出: Start 3 5 7 End
for item in enhanced_combined_generators():
    print(item)
    這里定義了一個輔助函數(shù) add_generators,它接受兩個生成器并逐個取出它們的元素相加以生成新的值。enhanced_combined_generators 則是在之前的基礎(chǔ)上加入了這個新功能。通過這種方式,你可以非常靈活地構(gòu)建復(fù)雜的生成器邏輯,而不需要為每一個可能的變化都編寫全新的生成器10。

綜上所述,yield 和 yield from 可以很好地協(xié)同工作,幫助開發(fā)者構(gòu)建高效、易于維護(hù)的生成器代碼。無論是簡單的串聯(lián)還是更復(fù)雜的操作,如數(shù)據(jù)變換或條件分支,都可以通過合理的設(shè)計達(dá)到預(yù)期的效果。重要的是要理解每種語句的作用以及它們?nèi)绾蜗嗷プ饔?,這樣才能寫出既強(qiáng)大又優(yōu)雅的 Python 代碼2。此外,yield from 的引入不僅簡化了代碼,還增強(qiáng)了生成器之間通信的能力,特別是在涉及到異常傳遞時顯得尤為重要14。因此,在實際編程實踐中,充分利用這兩種工具能夠極大地提升代碼的質(zhì)量和性能。

5.總結(jié)

  • yield函數(shù)屬性
    • 當(dāng)一個函數(shù)包含yield關(guān)鍵字時,這個函數(shù)就變成了一個生成器函數(shù)。
    • 調(diào)用生成器函數(shù)并不會立即執(zhí)行函數(shù)體內(nèi)的代碼,而是返回一個生成器對象。
    • 生成器對象可以被迭代,每次迭代時,生成器函數(shù)會從上次離開的地方繼續(xù)執(zhí)行,直到遇到下一個yield語句,然后返回一個值,并保存當(dāng)前狀態(tài),以便下次繼續(xù)執(zhí)行。
    • 這種行為使得生成器非常適合處理大量數(shù)據(jù)或流式數(shù)據(jù),因為它不需要一次性將所有數(shù)據(jù)加載到內(nèi)存中,從而節(jié)省了內(nèi)存資源。
  • yield vs return
    • return:當(dāng)函數(shù)執(zhí)行到return語句時,它會立即停止執(zhí)行,并返回一個值給調(diào)用。
      這意味著函數(shù)的局部變量會被銷毀,且函數(shù)的執(zhí)行狀態(tài)不會被保存。
      因此,如果再次調(diào)用同一個函數(shù),它將從頭開始執(zhí)行。
    • yield:與return不同,當(dāng)執(zhí)行到y(tǒng)ield語句時,函數(shù)會暫停執(zhí)行,返回一個值給調(diào)用者,并保存當(dāng)前的所有局部變量狀態(tài)。
      下次調(diào)用生成器時,函數(shù)將從上次暫停的地方恢復(fù)執(zhí)行,直到遇到下一個yield語句或函數(shù)結(jié)束。
  • 生成器的使用場景
    • 處理大數(shù)據(jù)集:由于生成器是惰性求值的,它可以在需要時才生成數(shù)據(jù),因此非常適合處理大數(shù)據(jù)集,避免了一次性加載所有數(shù)據(jù)導(dǎo)致的內(nèi)存不足問題。
    • 簡化代碼結(jié)構(gòu):使用生成器可以簡化代碼結(jié)構(gòu),尤其是當(dāng)需要處理復(fù)雜的狀態(tài)機(jī)或遞歸結(jié)構(gòu)時。
    • 協(xié)程與并發(fā):雖然Python的標(biāo)準(zhǔn)庫中已經(jīng)提供了多種并發(fā)模型,但生成器可以作為一種輕量級的協(xié)程實現(xiàn),用于實現(xiàn)簡單的并發(fā)任務(wù)。

到此這篇關(guān)于Python中yield函數(shù)用法詳解的文章就介紹到這了,更多相關(guān)Python yield函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

  • Python?eval()和exec()函數(shù)使用詳解

    Python?eval()和exec()函數(shù)使用詳解

    exec函數(shù)執(zhí)行的是python語句,沒有返回值,eval函數(shù)執(zhí)行的是python表達(dá)式,有返回值,exec函數(shù)和eval函數(shù)都可以傳入命名空間作為參數(shù),本文給大家介紹下Python?eval()和exec()函數(shù),感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • Anaconda+spyder+pycharm的pytorch配置詳解(GPU)

    Anaconda+spyder+pycharm的pytorch配置詳解(GPU)

    這篇文章主要介紹了Anaconda+spyder+pycharm的pytorch配置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • python如何使用騰訊云發(fā)送短信

    python如何使用騰訊云發(fā)送短信

    這篇文章主要介紹了python如何使用騰訊云發(fā)送短信,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-09-09
  • 深入理解NumPy簡明教程---數(shù)組1

    深入理解NumPy簡明教程---數(shù)組1

    這篇文章主要介紹了深入理解NumPy簡明教程(二、數(shù)組1),NumPy數(shù)組是一個多維數(shù)組對象,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • 實例探究Python以并發(fā)方式編寫高性能端口掃描器的方法

    實例探究Python以并發(fā)方式編寫高性能端口掃描器的方法

    端口掃描器就是向一批端口上發(fā)送請求來檢測端口是否打開的程序,這里我們以實例探究Python以并發(fā)方式編寫高性能端口掃描器的方法
    2016-06-06
  • Python3.7中安裝openCV庫的方法

    Python3.7中安裝openCV庫的方法

    這篇文章主要介紹了Python3.7中安裝openCV庫的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-07-07
  • PyCharm 解決找不到新打開項目的窗口問題

    PyCharm 解決找不到新打開項目的窗口問題

    這篇文章主要介紹了PyCharm 解決找不到新打開項目的窗口問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Python利用matplotlib繪制折線圖的新手教程

    Python利用matplotlib繪制折線圖的新手教程

    這篇文章主要給大家介紹了關(guān)于Python利用matplotlib繪制折線圖的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • python 求兩個向量的順時針夾角操作

    python 求兩個向量的順時針夾角操作

    這篇文章主要介紹了python 求兩個向量的順時針夾角操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • 最新評論