Python小知识点——生成器(generator)与关键字yield的运用

生成器(generator)是一种可迭代对象。

在处理包含大量数据时,如果使用list来进行操作,会导致内存占用大,效率低。生成器通过延迟计算,实现了一种边循环边计算的可能,只有在需要的时候才返回相应的结果,而不是一次性返回一整个结果列表,因此可以有效地节省了大量的空间。

首先,根据列表生成式,将[]改成()即可创建一个generator

>>> a = (x * x for x in [1,2,3])  # 列表生成式:a = [x * x for x in [1,2,3]]

# 如果你想转成list类型,可以直接用list(a)。

输出元素,可以使用next()

>>> next(a)
1
>>> next(a)
4
>>> next(a)
9

每一次调用next(a),a就会接着上一次的循环输出下一次的结果。当循环完全部元素后,再调用next(a),就会报错。

另外,因为生成器本身是可迭代对象,所以你也可以使用for in 循环遍历直接输出结果。

>>> for x in a:
	print(x)	
1
4
9

对生成器有了初步认识后,我们就可以开始掌握关键字yield了。

其实很简单,关键字yield的作用就是替代关键字return,如果一个函数中使用了yield来返回结果,我们就认为这个函数是一个生成器

def func(n):
    for i in range(1,n):
        result = i * i
        yield result

# 将(x * x for x in [1,2,3])用函数的方式表示

了解生成器(generator)与关键字yield的知识后

我们将上面的代码扩展一下

def func(n):
    for i in range(1,n):
        result = i * i
        yield result

func = func(5)
for x in func:
    print(x)
for x in func:
    print(x)

运行结果:

>>> 
1
4
9
16

结果可知,本应该输出了两次循环的结果,却只输出了一次循环。如果你在两个循环中间,添加一个print(list(func))语句,你就会发现由generator转换成list的func是空的,即func=[],func内部的元素似乎被“清空”了。

注意:一个生成器只能遍历一次。

为什么会这样呢?其实在调用next()方法的时候就大概明白了,每一次调用next()的时候,循环处于“工作”状态,不调用的时候,程序就处于一种“暂停”的状态,直到再次被调用,才会“工作”。当循环到最后一个元素后,我们再调用next()时就会报错。这说明了生成器只是代表了一次完整的循环中不断计算结果的过程。

那如果你还是希望能让你的生成器能被多次调用的话,你可以这样做

1、将生成器转换成list,再进行遍历

func = list(func(5))

2、需要遍历几次,就生成多少个可迭代对象(generator),再分别遍历

func1 = list(func(5))
func2 = list(func(5))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章