2.2.2 生成器推导式
从形式上看,生成器推导式与列表推导式非常接近,只是生成器推导式使用圆括号而不是列表推导式使用的方括号。与列表推导式不同的是,生成器推导式的结果是一个生成器对象,而不是列表,也不是元组。使用生成器对象的元素是,可以根据需要将其转化为列表或元组,也可以使用生成器对象的__next__()方法或者内置函数next()进行遍历,或者直接将其作为迭代器对象来使用。但是不管哪种方法访问其元素,当所有元素访问结束以后,如果需要重新访问其中的元素,必须重新创建该生成器对象。
1 >>> g = (( i + 2 ) ** 2 for i in range(10)) #创建生成器对象
2 >>> g
3 <generator object <genexpr> at 0x00000000035414C0>
4 >>>
5 >>> tuple(g) #将生成器对象转换为元组
6 (4, 9, 16, 25, 36, 49, 64, 81, 100, 121)
7 >>>
8 >>> list(g) #生成器对象已遍历结束,已经没有元素了
9 []
10 >>>
11 >>> g = (( i + 2 ) ** 2 for i in range(10))
12 >>>
13 >>> g.__next__() #使用生成器对象的__next__()方法获取元素
14 4
15 >>> g.__next__() #获取下一个元素
16 9
17 >>>
18 >>> next(g) #使用内置函数next()获取生成器对象中的元素
19 16
20 >>> next(g) #获取下一个元素
21 25
22 >>>
23 >>>
24 >>>
25 >>> g = (( i + 2 ) ** 2 for i in range(10))
26 >>>
27 >>> for item in g: #使用循环直接遍历生成器对象中的元素
28 print(item,end=' ')
29
30
31 4 9 16 25 36 49 64 81 100 121
32 >>>
小提示:
(1)生成器对象具有惰性求值的特点,只在需要时返回元素,比列表推导式具有更高的效率,尤其适合大量数据的遍历。
拓展知识:
生成器对象。包含yield语句的函数也可以用来创建可迭代的生成器对象。下面的diamante演示了如何使用生成器来生成斐波那契数列。
1 >>> def f():
2 a,b = 1,1 #序列解包,同时为多个元素赋值
3 while True:
4 yield a #暂停执行,需要时再产生一个新元素
5 a,b = b,a + b #序列解包,继续生成新元素
6
7
8 >>>
9 >>> a = f() #创建生成器对象
10
11 >>> for i in range(10): #获取斐波那契数列中前10个元素
12 print(a.__next__(),end = ' ')
13
14
15 1 1 2 3 5 8 13 21 34 55
16 >>>
17 >>>
18 >>>
19 >>>
20 >>>
21 >>> for i in f(): #获取斐波那契数列中第一个大于100的元素
22 if i > 100:
23 print(i)
24 break
25
26
27 144
28 >>>
29 >>> a = f()
30 >>> next(a) #使用内置函数next()获取生成器对象中的元素
31 1
32 >>>
33 >>> next(a) #每次获取新元素是,由yield语句返回。
34 1
35 >>>
36 >>> a.__next__()
37 2
38 >>>