这里是yield相关知识的目录
一.引言
本人是python新手,在阅读代码时碰到了这个奇怪的关键字…
因为在c和java里都没有遇到过,属于一点概念也没有
在查这个关键字的时候看了许多讲解
现整理如下
二.自己对于yield简洁的概括
yield : return里的迭代器
普通函数用return返回一个值
但是Python 中还有一种函数,用关键字yield来返回值,这种函数叫生成器
此时这个函数已经不是常规意义上的函数了,而是一个对象
例如
f=func() 意味着创建一个生成器(对象)命名为f
而不是意味着函数内部代码的运行
为什么说yield是return里的迭代器
return是什么? 用来返回值的
迭代器是什么? 是用于迭代操作的对象
yield就是用来一次又一次地返回值
三.上代码和解析
以最简单的代码为例
def func():
for i in range(0,3):
yield i
f = func()
print(f.__next__())#输出hello 0
print(f.__next__())#输出1
print(next(f))#输出2 next(f)和f.next()是等价的
print(f.__next__())#错误 StopIteration 原因 已停止
# f.next() 在3.1.x版本前是next 后改成__next__
1 f=func()
生成一个生成器,命名为f(可以理解成是一个对象)
并不是运行这个函数(原因:此时并没有打印出hello)
2 f.__ next __()
调用next方法,运行这个生成器
先运行print(‘hello’),打印出hello
再运行到for循环中,此时的i值为0,故返回值是0,然后暂停运行
再由print函数打印出返回值1
后边两个print依次打印出1,2
3 最后一个print
由于for循环结束,生成器不再生成值(stop iteration)返回了,故报错
即 每一次调用它的__next__方法都会返回一个值
稍微加一点点难度
def demo():
print("hello")
while True:
res = yield 520
print("res:",res)
f = demo()
print(next(f))
print('---------')
print(next(f))
区别:多了个赋值
相信读者有点疑惑的地方应该在None
来单步调试,解读一下:
1.f=demo()
demo函数中有yield关键字,相当与一个生成器,demo函数不会执行,
而是得到一个生成器f(相当于一个对象)
2.print(next(f))
将这句代码理解成两个步骤
1 先调用next方法
调用next方法,demo函数正式执行
先调用demo函数中的print方法,再进入while循环
程序遇到yield关键字,yield 520 理解成 return 520
程序暂时停止,但是没有给res赋值(原因:到yield就结束了 按照顺序 赋值本来在yield的下一步)
2 再print出next方法的返回值
输出返回值是520
3.print(‘---------’),输出一条分割线
4.print(next(f))
执行第二条print(next(f)),与第二步类似
区别在于:从刚才那个next程序停止的地方(yield处)开始
(除了第一次next,后续的next方法都是从上一次的yield后开始)
要执行res的赋值操作但是此时等号右边没有值(因为刚才那个是return出去了,尚未进行赋值操作),所以res是None,故输出就是res:None
继续while里执行,再次碰到yield,这个时候同样return 520,返回值是520,然后程序停止
打印出返回值520
所以yield是什么,有什么用
再来重新理解一下:
带yield的函数是一个生成器,而不是一个函数了
这个生成器有一个函数是next函数,next就相当于“下一步”生成哪个数
这一次的next开始的地方接着上一次的yield的地方执行
四.生成器(带yield的函数)的作用/优点
1.延迟计算,减少内存占用
一次返回一个结果,防止处理很大的数据量的时候内存占用过大
例:
一次生成1-10000的数的列表内存占用大于使用生成器所占内存
列表是在建立的时候就分配所有的内存空间
生成器只需要每次调用每次生成就好了