自学Python之yield
这段时间老师给安排的任务,看别人的代码,所以我还要不停的补充其语言知识(也就是python),今天就碰到了yeild,不解其意,故来以文记之,我是小白,欢迎指正。
关于生成器的详细使用和介绍请参见官方文档,我这里只是自己的想法和思考过程
1 什么是yield?
如果你不太喜欢理论部分的话,那我们先看看他是干啥的(可以先从第二节开始看),怎么用,然后在回来看yield到底是个什么东西
说是yield,其实他只是一个用来产生生成器(generator)的一个关键字,所以这篇主要讲生成器。
yield
关键字放在函数中,可以让我们写的函数变成generator
对象(也就是为什么res指向的内容是fun,见下一节)
此时yield就有些类似debug中的断点了,在我们迭代generator的时候,迭代一次就相当于从上一次yield的地方继续执行函数(变量什么的都不会变,就像到断点停下来,然后又可以继续执行似的),一直到再次碰到yield就会停止执行,并且把yield后面的数据返回给迭代者。就像下面这张图:
2 yield怎么用?
用法:使用yield可以就把它放在需要返回值的地方,用法和return相似。yield可以和return同时存在函数中
这里先举个简单的例子: )
def fun(n):
for i in range(n):
yield i
if i > 3:
return 'I don\'t like yield'
res=fun(5)
print('the res is ' + res)
print('the content of res:')
for i in res:
print(i)
执行它返显示的内容是下面这样:
the res is <generator object fun at 0x000002609701C0F8>
the content of res:
0
1
2
3
我们根据这个执行结果,首先可以知道,函数的返回值好像是一个generator
对象,但是请注意,他的名字居然和我们的函数是同一个名字,这就有趣了。继续来看我们的执行结果,我们对res可以进行遍历然后输出,所以表面上看起来generator
的功能就像是一个数组(元组)的功能差不多。但是,执行在文件中添加下面代码
print(len(x))
你会发现报错了,就问你尴尬不尴尬,这个x没有长度,那么就可以判断他,并不是单纯的类似数组的东西(Python开发人员又不傻)
现在可以回到第一节 去看看理论上的yield是什么。
然后现在来看对generator对象迭代的方法。
# 假设x是一个generator对象
#1 for 循环
for temp in x:
print(temp)
#2 对象的next()方法
res1=x.next()
res2=x.next()
...
##注意第二种方法如果迭代完成还要next()会抛出异常。
###也就是说,一个生成器对象只能遍历一次。
3 什么情况下使用yield
什么情况下要使用yield呢,我用数组或者元组去返回结果不是很好嘛?
现在这个情况,如果数据特别多的话,在加上处理方法复杂,可能我们函数结果占用的内存就会无比巨大,如果使用generator 、yield的话,我们的空间复杂度就是常数级的,因为每次都迭代都是执行一次函数里的循环,得到一条结果,用完之后就扔掉了(当然你也可以用外层变量把它存起来)
- 代码量更少,首先少了定义返回对象的代码,还有额外的循环代码
- 更省内存,前面说了
- 可读性更好,如果你理解了生成器的概念,那么代码的逻辑会更清晰