
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函数。当需要一次获取一组元素的值时,使用序列。