python生成器函數(shù)yield與yield?from使用
一、為什么叫生成器函數(shù)?
因為它們產生generate一系列值而得名。在生成器函數(shù)中,使用"yield"語句生成一個值并將其返回調用值,而不是通過普通的"return"語句一次性返回所有值。
因為生成器函數(shù)只有在請求下一個值時,才會進行計算,并且在生產值時保留函數(shù)的狀態(tài)。所以,處理大量的數(shù)據時,不會占用很大的內存。他們不會一次性計算并存儲所有的值,所以主要特點是『惰性計算』。
- 好處:高效地使用內存和計算資源。
- 最大特點:惰性計算。(用的時候,才去計算。)
- 保留狀態(tài):保留之前的值。
如下代碼,yiled調用生成器,返回的是一個generator類型的值。

1、yield在生成器函數(shù)中使用
生成器是一種特殊的函數(shù)。
生成器函數(shù)中的 "yield" 關鍵詞用于產生值并將其返回給調用者,同時保留函數(shù)的當前狀態(tài)。
每次調用生成器函數(shù)時,它會從上次 "yield" 語句的位置恢復執(zhí)行,并一直執(zhí)行到下一個 "yield" 語句。這樣,生成器函數(shù)可以逐步生成值,而不是一次性生成所有值,從而節(jié)省內存并提高性能。
如下代碼,是一個生成器函數(shù),它會生成一系列整數(shù)值:1,2,3。
def nested_generator():
yield 1
yield 2
yield 3二、怎么使用generator類型的數(shù)據?
生成器generator是一種特殊類型的迭代器。
1、什么是迭代器?
迭代器Iterator,用來一種遍歷或迭代集合元素的對象??梢园错樞蛟L問集合的每個元素,而無需了解集合內部的結構。用iter和next手動操作迭代器。

for循環(huán)無法獲取到迭代的值,因為迭代器已遍歷完所有的值。
2、generator生成器里可以放什么類型的數(shù)據?
在生成器中,可以放置各種類型的東西,包括 yield 語句、函數(shù)調用、表達式、迭代器以及 yield from 表達式。這些元素共同構成了生成器函數(shù)的功能,使其能夠高效地處理大型數(shù)據集、無限序列或需要惰性計算的場景。
3、怎么使用generator類型的數(shù)據?
generator是一種特殊的迭代器。因為iterator可用next,不可以用for循環(huán)。但是gerater兩者都可以用。
1、獲取值的方式
def my_generator():
yield 1
yield 2
yield 3
# 使用 for 循環(huán)迭代生成器
for value in my_generator():
print(value)
# 使用 next() 函數(shù)
gen = my_generator()
print(next(gen)) # 輸出:1
print(next(gen)) # 輸出:2
print(next(gen)) # 輸出:32、可直接用于迭代函數(shù),如sum()、max()、min() 等。
gen = my_generator() total = sum(gen) print(total) # 輸出:6
3、generator和其他類型的互相轉換
1、generator轉換成其他類型(例如列表、元祖、集合)。如下代碼
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
my_list = list(gen) # 或者 tuple(gen)、set(gen)
print(my_list) # 輸出:[1, 2, 3]
2、其他類型轉換成generator類型
(1)使用生成器表達式
my_list = [1, 2, 3, 4, 5] gen = (x for x in my_list)
(2)函數(shù)中使用yield
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()三、yield from使用
1、如果解讀如下代碼段?
def nested_generator():
yield 1
yield 2
yield 3
def main_generator():
yield 'Start'
yield from nested_generator()
yield 'End'
def ok_yiled_from():
for item in main_generator():
print(item)
ok_yiled_from()
輸出:
Start
1
2
3
End1、ok_yiled_from調用main_generator返回一個generator,進行for循環(huán)。
2、調用main_generator中的yield 'Start',則生成Start并返回給調用者,執(zhí)行到該句返回,并暫停
3、調用main_generator中的yield from nested_generator(),使用yield from調用另外一個生成器函數(shù)nested_generator()(問題:yield from后面只能跟生成器函數(shù)嗎?)。
main_generator生成器函數(shù)將執(zhí)行權轉交給nested_generator(),并在其中生成的值被產生時,直接返回main_generator生成器函數(shù)的調用者ok_yiled_from。main_generator暫停執(zhí)行,等待nested_generator執(zhí)行完畢。
4、當nested_generator()生成器函數(shù)執(zhí)行完畢后并沒有更多值可產生時,main_generator生成器函數(shù)會繼續(xù)執(zhí)行,yield 'End' 產出 End值。此時,生成器函數(shù)的執(zhí)行完全終止。
這樣,整個過程就形成了一個流程,生成器函數(shù)逐步生成值并在必要時暫停執(zhí)行,而在 yield from 語句中調用的嵌套生成器負責生成中間的值。這種機制使得生成器函數(shù)能夠高效地處理大量數(shù)據或延遲計算,從而節(jié)省內存和提高性能。
2、yield from后面要求跟什么?
yield from后面可以跟可迭代對象或者生成器generator。
1)跟任何可迭代對象iterable,包括列表、元組、集合、字典的鍵或值、字符串等
例如:
def list_generator():
my_list = [1, 2, 3, 4, 5]
yield from my_list
gen = list_generator()
for value in gen:
print(value)
2)跟生成器generator
如上面例子中的nested_generator()
3、yield后面跟什么?
yeild后面跟:不同類型單獨的值、任何不同類型的表達式、語句。
def calculate_square(x):
return x * x
def my_generator():
yield 1
yield "Hello"
yield 3.14
yield 10 * 2
yield calculate_square(2)
gen = my_generator()
print(next(gen)) # 輸出:1
print(next(gen)) # 輸出:hello
print(next(gen)) # 輸出:3.14
print(next(gen)) # 輸出:20
print(next(gen)) # 輸出:44、yield from和yield的相同和不同點是什么
相同點:
1)都是用來返回和暫停
2)都是生成器函數(shù),返回generator對象。
不同點:
1)返回給的對象不一樣。
(也就是:用yield for和yiled修飾函數(shù)有什么不同?也就是返回給的函數(shù)不一樣。)
yield產出的值返回給當前調用的函數(shù)。yiled from返回給當前調用函數(shù)的上一個調用函數(shù)。
- a. yield產生一個值,并將起返回給調用者;
- b. yield from 用于委托部分工作給另外一個生成器。它在生成器中使用,可以將另外一個生成器/迭代器產出的值直接返回給調用者。
代碼說明如下:
def generate_list():
return [1,3,4,5]
def while_yiled():
for i in range(0,2):
yield generate_list()
def while_yiled_from():
for i in range(0,2):
yield from generate_list()
print(list(while_yiled()))
print(list(while_yiled_from()))
輸出:
[[1, 3, 4, 5], [1, 3, 4, 5]]
[1, 3, 4, 5, 1, 3, 4, 5]解讀如上代碼:
1、def while_yiled(): ...
生成器函數(shù)while_yiled() ,每次循環(huán)中生成[1,3,4,5], 把作為一個單獨的元素返回給調用者print()函數(shù),2次循環(huán),得到了2個[1,3,4,5]元素,即結果為[[1,3,4,5]],[1,3,4,5]]]
2、while_yiled_from()
另外一個生成器函數(shù)while_yiled_from(),每次循環(huán)生成[1,3,4,5],直接把每個元素逐個返回給調用者print(),2次循環(huán),得到了共8個元素,即結果為[1,3,4,5,1,3,4,5]
總結:
while_yiled()和while_yiled_from()兩個生成器函數(shù)中,使用了不同的生成器特性:
- yiled返回整個結果給調用者。
- yiled form直接將返回的值逐個返回給調用者。
5、解讀如下代碼
def nested_generator():
yield 1
yield 2
yield 3
def main_generator_yeild_form():
yield 'Start'
yield from nested_generator()
yield 'End'
def main_generator_no_yield():
yield 'Start'
nested_generator()
yield 'End'
def main_generator_only_yield():
yield 'Start'
yield nested_generator()
yield 'End'
def try_yiled_from():
for item in main_generator_yeild_form():
print(item)
print('main_generator_yeild_form\n\n')
for item in main_generator_only_yield():
print(item)
print('main_generator_only_yield\n\n')
for item in main_generator_no_yield():
print(item)
print('main_generator_no_yield\n\n')
try_yiled_from()
輸出:
Start
1
2
3
End
main_generator_yeild_form
Start
<generator object nested_generator at 0x7fa9f4528930>
End
main_generator_only_yield
Start
End
main_generator_no_yield1、def main_generator_yeild_form():...
生成器函數(shù),使用yeild from 委托 nested_generator() 生成器進行工作,將返回的每個元素直接逐個給了調用者try_yiled_from中的main_generator_yeild_form(),所以結果就是:start、1、2、3、end
2、def main_generator_no_yield():...
生成器函數(shù),因為調用nested_generato()是并沒有使用yield、yield from,所以并沒有將nested_generato()產生的值返回給調用者。nested_generato()仍然會產生值,但是在調用者try_yiled_from中的main_generator_no_yield()中,并沒有返回,或者捕獲到。因此它的值不會被輸出。廢值,沒用過。
3、def main_generator_only_yield():...
生成器函數(shù),調用nested_generato()是使用yield,所以返回的是生成器本身,并不是nested_generato()產生的值,所以輸出結果為start, nested_generato()生成器對象,end。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Pycharm自動添加文件頭注釋和函數(shù)注釋參數(shù)的方法
這篇文章主要介紹了Pycharm自動添加文件頭注釋和函數(shù)注釋參數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10
Python數(shù)據分析與處理(一)--北京高考分數(shù)線統(tǒng)計分析
這篇文章主要介紹了Python數(shù)據分析與處理北京高考分數(shù)線統(tǒng)計分析,文章問繞Python數(shù)據分析與處理相關資料的介紹,展開對北京高考分數(shù)線統(tǒng)計分析,需要的小伙伴可以參考一下2021-12-12

