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

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

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

python官方api地址

1. yield介紹

在Python中,yield關(guān)鍵字主要用于生成器函數(shù)(generator functions)中,其目的是使函數(shù)能夠像迭代器一樣工作,即可以被遍歷,但不會(huì)一次性將所有結(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)遍歷生成器生成器對(duì)象是可迭代的,因此可以使用 for 循環(huán)來(lái)遍歷生成器生成的值。
    下面例子中,for 循環(huán)遍歷生成器函數(shù)生成的所有值,并依次打印它們。
def simple_generator():
    yield 1
    yield 2
    yield 3

for value in simple_generator():
    print(value)
  • 生成器表達(dá)式下面例子中,生成器表達(dá)式生成了一個(gè)平方數(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高級(jí)用法

3.1 yield send() 方法

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

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

這種方式可以實(shí)現(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

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

3.2 yield from方法

從Python 3.3開(kāi)始,引入了 yield from 語(yǔ)法,它允許一個(gè)生成器委托另一個(gè)生成器來(lái)生成值。

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

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)部資源編號(hào)用完,開(kāi)始使用外包')
    yield from outsource_pool()

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

運(yùn)行結(jié)果:

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

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

3.3 yield 和yield from疊加

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

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

  • 使用 yield 和 yield from 組合生成器當(dāng)你想要組合兩個(gè)或更多個(gè)生成器時(shí),你可以使用 yield 來(lái)逐個(gè)產(chǎn)出每個(gè)生成器中的元素,或者使用 yield from 來(lái)直接委托給子生成器,讓其負(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)出每個(gè)生成器中的元素
    for value in generator_a():
        yield value
    for value in generator_b():
        yield value
    
    # 或者使用 yield from 委托給子生成器
    yield from generator_a()
    yield from generator_b()

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

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

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

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

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

  • 結(jié)果的實(shí)際疊加如果我們談?wù)摰氖菍?shí)際的結(jié)果疊加(如數(shù)值相加),那么你需要明確地編寫(xiě)邏輯來(lái)實(shí)現(xiàn)這一點(diǎn)。
    比如,如果你想把來(lái)自不同生成器的數(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ù)接收兩個(gè)生成器作為參數(shù),并分別對(duì)它們求和后再相加。
請(qǐng)注意,這種方法會(huì)立即消耗掉這兩個(gè)生成器的所有元素并計(jì)算出總和,這可能不是最有效的做法,特別是對(duì)于非常大的數(shù)據(jù)集。

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

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

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

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

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

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

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

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

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

例如,假設(shè)你想把兩個(gè)生成器的結(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é)果可以通過(guò)編程邏輯被“疊加”,但這取決于你想要實(shí)現(xiàn)的具體行為。

如果是簡(jiǎn)單的迭代輸出,則可以直接使用 yield from 來(lái)簡(jiǎn)化代碼;

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

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

  • 處理大數(shù)據(jù)集生成器非常適合處理大數(shù)據(jù)集,因?yàn)樗梢栽谛枰獣r(shí)按需生成值,而不是一次性將所有值加載到內(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='')

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

  • 實(shí)現(xiàn)協(xié)程和并發(fā)生成器可以用于實(shí)現(xiàn)協(xié)程和并發(fā)編程模式。
    協(xié)程是一種用戶態(tài)的輕量級(jí)線程,可以用來(lái)模擬異步操作,實(shí)現(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

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

  • 數(shù)據(jù)處理管道生成器可以用于實(shí)現(xiàn)數(shù)據(jù)處理管道,每個(gè)生成器函數(shù)負(fù)責(zé)一個(gè)處理步驟。
    這種模式可以將復(fù)雜的任務(wù)分解為多個(gè)簡(jiǎn)單的步驟,提高代碼的可讀性和可維護(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)

在這個(gè)例子中,數(shù)據(jù)經(jīng)過(guò)兩個(gè)生成器函數(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)
    這里定義了一個(gè)輔助函數(shù) add_generators,它接受兩個(gè)生成器并逐個(gè)取出它們的元素相加以生成新的值。enhanced_combined_generators 則是在之前的基礎(chǔ)上加入了這個(gè)新功能。通過(guò)這種方式,你可以非常靈活地構(gòu)建復(fù)雜的生成器邏輯,而不需要為每一個(gè)可能的變化都編寫(xiě)全新的生成器10。

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

5.總結(jié)

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

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

相關(guān)文章

最新評(píng)論