python yield和yield from用法總結(jié)
yield 作用:
注: generator的next()方法在python 2中為next()外遇,但在python 3中為 __next__()
【next的前后各是兩個下劃線】
把一個函數(shù)變成一個generator契吉,帶有yield的函數(shù)不再是一個普通函數(shù)。即:一個帶有 yield 的函數(shù)就是一個 generator捐晶,它和普通函數(shù)不同,生成一個 generator 看起來像函數(shù)調(diào)用谨究,但不會執(zhí)行任何函數(shù)代碼泣棋,直到對其調(diào)用 next()(在 for 循環(huán)中會自動調(diào)用 next())才開始執(zhí)行。雖然執(zhí)行流程仍按函數(shù)的流程執(zhí)行潭辈,但每執(zhí)行到一個 yield 語句就會中斷,并返回一個迭代值寄摆,下次執(zhí)行時從 yield 的下一個語句繼續(xù)執(zhí)行修赞。看起來就好像一個函數(shù)在正常執(zhí)行的過程中被 yield 中斷了數(shù)次柏副,每次中斷都會通過 yield 返回當(dāng)前的迭代值。
yield 的好處是顯而易見的眷篇,把一個函數(shù)改寫為一個 generator 就獲得了迭代能力荔泳,比起用類的實(shí)例保存狀態(tài)來計(jì)算下一個 next() 的值,不僅代碼簡潔昧港,而且執(zhí)行流程異常清晰支子。
用print實(shí)現(xiàn)打印斐波拉切數(shù)列 ——基礎(chǔ)版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def fab(max):
n , a, b = 0, 0 , 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
if __name__ == '__main__':
fab(6) # 1 1 2 3 5 8
用yield實(shí)現(xiàn)打印斐波拉切數(shù)列——升級版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def fab(max):
n , a, b = 0, 0 , 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
if __name__ == '__main__':
for n in fab(6): # 1 1 2 3 5 8
print(n)
如何判斷一個函數(shù)是否是一個特殊的generator函數(shù)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from inspect import isgeneratorfunction
def fab(max):
n , a, b = 0, 0 , 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
if __name__ == '__main__':
f1 = fab(3)
# True fab是一個generator function
print(isgeneratorfunction(fab))
# False fab(3)不是一個generator function
# 而fab(3)是調(diào)用fab返回的一個generator
print(isgeneratorfunction(fab(3)))
用yield實(shí)現(xiàn)大文件讀取
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def read_file(fpath):
BLOCK_SIZE = 100
with open(fpath, "rb") as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return
if __name__ == '__main__':
fpath = "/home/exercise-python3.7.1/vote/mysite/mysite/polls/test.txt"
read_gen = read_file(fpath)
print(read_gen.__next__())
print(read_gen.__next__())
print(read_gen.__next__())
print(read_gen.__next__())
# for循環(huán)會自動調(diào)用generatr的__next__()方法,故輸出效果同如上的4個print 【內(nèi)容較短瓤的,4個print就將test.txt中的內(nèi)容輸出完了】
for data in read_gen:
print(data)
yield 和 yield from 用法對比
使用yield拼接可迭代對象
#!/usr/bin/env python
# -*- coding: utf-8 -*-
if __name__ == '__main__':
astr = "ABC"
alist = [1, 2, 3]
adict = {"name": "wangbm", "age": 18}
# generate
agen = (i for i in range(4, 8))
def gen(*args, **kw):
for item in args:
for i in item:
yield i
new_list = gen(astr, alist, adict, agen)
print(list(new_list))
# ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]
使用yield from拼接可迭代對象
#!/usr/bin/env python
# -*- coding: utf-8 -*-
if __name__ == '__main__':
astr = "ABC"
alist = [1, 2, 3]
adict = {"name": "wangbm", "age": 18}
# generate
agen = (i for i in range(4, 8))
def gen(*args, **kw):
for item in args:
yield from item
new_list = gen(astr, alist, adict, agen)
print(list(new_list))
# ['A', 'B', 'C', 1, 2, 3, 'name', 'age', 4, 5, 6, 7]
結(jié)論:
由上面兩種方式對比圈膏,可以看出,yield from后面加上可迭代對象稽坤,他可以把可迭代對象里的每個元素一個一個的yield出來,對比yield來說代碼更加簡潔睦擂,結(jié)構(gòu)更加清晰杖玲。
參考資料:
http://www.cnblogs.com/wongbingming/p/9085268.html
https://www.cnblogs.com/python-life/articles/4549996.html