零基础学Python(第2版)
上QQ阅读APP看书,第一时间看更新

5.3.7 Generator函数

生成器(Generator)的作用是一次产生一个数据项,并把数据项输出。Generator函数可以用在for循环中遍历。Generator函数每次返回一个数据项的特性,使得迭代器的性能更佳。Generator函数的定义如下所示。


01     def 函数名(参数列表):
02          …
03          yield 表达式

Generator函数的定义和普通函数的定义没有什么区别,只要在函数体内使用yield生成数据项即可。Generator函数可以被for循环遍历,而且可以通过next()方法获得yield生成的数据项。下面【例5-17】这段代码演示了Generator函数的使用。

【例5-17.py】


01     # 定义Generator函数
02     def func(n):
03         for i in range(n):
04             yield i
05     # 在for循环中输出
06     for i in func(3):
07         print (i)
08     # 使用next()输出
09     r =  func(3)
10     print (r. __next__())
11     print (r. __next__())
12     print (r. __next__())
13     print (r. __next__())

【代码说明】

·第2行代码定义了Generator函数,参数n表示一个数字,该函数依次生成0到n个数字。

·第4行代码调用yield生成数字。

·第6行代码遍历函数func(),依次输出yield生成的数字。输出结果:


0
1
2

·第9行代码把func()赋值给变量r。

·第10行到第12行代码,输出r.__next__()的值。输出结果:


0
1
2

·第13行代码再次调用r.__next__()。由于n的值等于3,生成3个数字后,已经没有数据可生成。Python解释器抛出异常StopIteration。

yield关键字与return关键字的返回值和执行原理都不相同。yield生成值并不会中止程序的执行,返回值后程序继续往后执行。return返回值后,程序将中止执行。下面【例5-18】这段代码演示了yield和return的区别。

【例5-18.py】


01     # yield与return区别
02     def func(n):
03         for i in range(n):
04             return i
05     def func2(n):
06         for i in range(n):
07             yield i
08
09     print (func(3))
10     f = func2(3)
11     print (f)
12     print (f. __next__())
13     print (f. __next__())

【代码说明】

·第4行代码直接返回i的值,循环语句将被中止,整个程序到此结束。

·第7行代码循环生成n个数字,循环语句不会被中止。

·第9行代码的输出结果为“0”。

·第11行代码,yield并没有返回任何值,而是返回了函数func2()的地址。输出结果:


<generator object func2 at 0x00000231FA39CE48>

·第12行代码,调用f.__next__()才能获得返回值。输出结果为“0”。

·第13行代码的输出结果为“1”。

Generator函数可以返回元素的值,而序列也可以获取元素的值。但是两者还是存在很大的区别。Generator函数一次只返回一个数据项,占用更少的内存。每次生成数据都要记录当前的状态,便于下一次生成数据。数据的访问是通过__next__()方法实现的。当访问越界时,Generator函数会抛出异常StopIteration。序列一次返回所有的数据,元素的访问是通过索引完成的。当访问越界时,序列提示list index out of range错误。

当程序需要较高的性能或一次只需要一个值进行处理时,使用Generator函数。当需要一次获取一组元素的值时,使用序列。