Python3的yield用法
前言
在学习爬虫时,出现yield
关键词,不明白他的用法,看了篇文章给了我启发,在其基础上还发现一些特征。我的Python水平低,不知道理解的对不对,还请评论指出错误。本文在Python3.8
环境下运行
正文:
首先,如果你还没有对yield有个初步分认识,那么你先把yield看做“return”,这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了。看做return之后再把它看做一个是生成器(generator)的一部分(带yield的函数才是真正的迭代器)
——出自python中yield的用法详解——最简单,最清晰的解释
我的理解:yield
跟return
用法相似,yield
返回迭代器
,遍历返回的迭代器时,程序先截止于yield,下次遍历会接着上次
程序同级
继续运行,并在最后一次遍历不会在yield截止程序,会继续运行;return
返回某个值,程序不再往下运行。
先脑子里不要带东西,来看示例。
示例1(return与yield返回值区别):
#示例1-1
def foo(num):
for i in num:
return i
num=[1, 2, 3, 4, 5]
demo = foo(num)
print(demo)
'''返回值:
1
'''
#示例1-2
def foo(num):
for i in num:
yield i
num=[1, 2, 3, 4, 5]
demo = foo(num)
print(demo)
'''返回值:
<generator object foo at 0x000001D277EA29E0>
'''
由上可知:return
返回值,yield
返回可迭代对象
示例2(return与yield程序截止区别):
#示例2-1
def foo(num):
for i in num:
return i
print('end'+str(i))
num=[1, 2, 3, 4, 5]
demo = foo(num)
print(demo)
print("*"*20)
print(demo)
print("*"*20)
print(demo)
'''返回值:
1
********************
1
********************
1
'''
#示例2-2
def foo(num):
for i in num:
yield i
print('end'+str(i))
num=[1, 2, 3, 4, 5]
demo = foo(num)
#next()返回迭代器的下一个项目(项目在本示例是一个数值)
print(next(demo))
print("*"*20)
print(next(demo))
print("*"*20)
print(next(demo))
'''返回值:
1
********************
end1
2
********************
end2
3
'''
示例2-1使用return并没有执行函数中return之后的代码。
示例2-2使用yield,遍历第一个项目返回1,即截止于yield i
,没有执行print('end'+str(i))
;
遍历第二个项目先返回end1
,再返回2
,即先接着上次yield i
截止处继续运行,所以此时i
等于1
,输出end1
,再重新执行一遍程序,截止于yield i
,返回2;
第三次遍历同理
(注:yield i
与print('end'+str(i))
同级,在同一个循环下,同级运行,无需跳出循环,不知道怎么形容了)
示例3(同级与不同级区别)
#示例3-1 与示例2-2一样
def foo(num):
for i in num:
yield i
print('end'+str(i))
num=[1, 2, 3, 4, 5]
demo = foo(num)
#next()返回迭代器的下一个项目(项目在本示例是一个数值)
print(next(demo))
print("*"*20)
print(next(demo))
print("*"*20)
print(next(demo))
'''返回值:
1
********************
end1
2
********************
end2
3
'''
#示例3-2
def foo(num):
for i in num:
yield i
print('end'+str(i)) ####修改处
num=[1, 2, 3, 4, 5]
demo = foo(num)
#next()返回迭代器的下一个项目(项目在本示例是一个数值)
print(next(demo))
print("*"*20)
print(next(demo))
print("*"*20)
print(next(demo))
'''返回值:
1
********************
2
********************
3
'''
示例3-1,yield i
与print('end'+str(i))
同级,遍历第一项目不执行print
,第二、三个项目执行print
示例3-2,yield i
与print('end'+str(i))
同级,遍历第一、二、三个项目均不执行print
(注:foo()返回一共有五个项目)
示例4(遍历所有项目,遍历前部分项目区别):
示例4-1
def foo(num):
for i in num:
yield i
print('end'+str(i))
num=[1, 2, 3, 4, 5]
demo = foo(num)
#遍历迭代器所有项目
while True:
try:
print(next(demo))
print("*" * 20)
except StopIteration:
break
'''返回值:
1
********************
2
********************
3
********************
4
********************
5
********************
end5
'''
示例3-2与示例4-1对比:
foo()函数返回的迭代器一共有五个项目。
示例3-2,遍历前三个项目都没有输出print;
示例4-1,遍历所有项目,在遍历最后一个项目时,和前面几个相同,先截止于yield i
,执行完主程序代码后,不过会继续执行带yield函数的剩余代码(不管代码与yield
是否同级,附上对比示例4-2)。最后print(next(demo))
,打印出5,截止在yield 5,先打印主程序中的*
,再打印函数中的end5
示例4-2
def foo(num):
for i in num:
yield i
print('end'+str(i))
num=[1, 2, 3, 4, 5]
demo = foo(num)
#遍历迭代器所有项目
while True:
try:
print(next(demo))
print("*" * 20)
except StopIteration:
break
'''返回值:
1
********************
end1
2
********************
end2
3
********************
end3
4
********************
end4
5
********************
end5
'''
总结:
yield相当于一个迭代生成器。带有yield的函数是迭代函数,返回一个可迭代对象;在遍历其部分迭代项目时,获取下一个项目会沿着上一次yield截止处,继续运行同级代码后,再重头运行函数;yield后的不同级代码只有获取最后一个项目后运行。
下次多看一些文章,有新的内容再补充。