朋友们,如需转载请标明出处:https://blog.csdn.net/jiangjunshow
声明:在人工智能技术教学期间,不少学生向我提一些python相关的问题,所以为了让同学们掌握更多扩展知识更好地理解AI技术,我让助理负责分享这套python系列教程,希望能帮到大家!由于这套python教程不是由我所写,所以不如我的AI技术教学风趣幽默,学起来比较枯燥;但它的知识点还是讲到位的了,也值得阅读!想要学习AI技术的同学可以点击跳转到我的教学网站。PS:看不懂本篇文章的同学请先看前面的文章,循序渐进每天学一点就不会觉得难了!
生成器函数和常规函数一样,并且,也是用常规的def语句编写的。然而,当创建时,它们自动实现迭代协议,以便可以出现在迭代背景中。和返回一个值并退出的常规函数不同,生成器函数自动在返回一个生成值的时刻挂起并继续上层函数的执行。
生成器函数和常规函数之间的主要的代码不同之处在于,生成器yield一个值,而不是return一个值。yield语句挂起该函数并向调用者发送回一个值,当再次调用这个生成器函数时,它里面的yield语句会接着上次的状态并且再次产生一个值返回给调用者。这允许其代码随着时间产生一系列的值,而不是一次计算它们并在诸如列表的内容中送回它们。
上面的解释还是比较难理解的,大家看如下代码再来慢慢理解,下面代码定义了一个生成器函数,这个函数将会用来不断地生成一系列的数字的平方。
>>>def gensquares(N):
... for i in range(N):
... yield i ** 2 # Resume here later
...
这个函数在每次循环时都会产生一个值,之后将其返还给它的调用者。当它被暂停后,它的上一个状态保存了下来,并且在yield语句之后控制器马上被回收。例如,当用在一个for循环中时,在循环中每一次完成函数的yield语句后,控制权都会返还给函数。
>>>for i in gensquares(5): # Resume the function
... print(i,end=' : ') # Print last yielded value
...
0 : 1 : 4 : 9 : 16 :
如果想要看看在for里面发生了什么,直接调用一个生成器函数:
>>>x = gensquares(4)
>>>x
得到的是一个生成器对象,它支持迭代器协议,也就是说,生成器对象有一个__next__方法,它可以开始这个函数,或者从它上次yield值后的地方恢复,并且在得到一系列的值的最后一个时,产生StopIteration异常。
next(X)内置函数为我们调用一个对象的X.__next__()方法:
>>>next(x) # Same as x.__next__() in 3.0
0
>>>next(x) # Use x.next() or next() in 2.6
1
>>>next(x)
4
>>>next(x)
9
>>>next(x)
Traceback (most recent call last):
...more text omitted...
StopIteration
我们能够简单地构建一个一次性就获得所有的值的列表。
>>>def buildsquares(n):
... res = []
... for i in range(n): res.append(i ** 2)
... return res
...
>>>for x in buildsquares(5): print(x,end=' : ')
...
0 : 1 : 4 : 9 : 16 :
我们还能够使用for循环、map或者列表解析的技术来实现:
>>>for x in [n ** 2 for n in range(5)]:
... print(x,end=' : ')
...
0 : 1 : 4 : 9 : 16 :
>>>for x in map((lambda n: n ** 2),range(5)):
... print(x,end=' : ')
...
0 : 1 : 4 : 9 : 16 :
但是生成器在内存使用和性能方面都更好。它们允许函数避免一次性做完所有的工作,当结果的列表很大或者在处理每一个结果都需要很多时间时,这一点尤其有用。生成器将loop迭代中处理一系列值的时间分布开来。