一、生成器:generator
按照规则去生成一定的数据
1、列表推导式和生成器的区别
列表推导式: 一次性生成所有满足条件的数据
生成器: 你要一个数据, 我生成出来给你一个
2、生成器表达式
生成器对象 = (表达式 for item in 容器)
生成器对象 = (表达式 for item in 容器 if 条件)
生成器对象 = (表达式 for item in 容器 for item2 in 容器2)
3、通过生成器对象获取数据
(1)next(g)
(2)for in 依次获取生成器对象中的每个数据
(3) g.__next__()
(4)send(值):给上一次生成器函数中yield的位置传递一个值
第一次获取生成器数据时, 不能使用send()方法获取
1 # 1、生成1-10的数据的生成器
2 g = (x for x in range(1, 11))
3 print(type(g)) # <class 'generator'>
4 print(g) # <generator object <genexpr> at 0x00000000007EA948>
5
6 print(next(g)) # 1 获取g对象的数据
7 print(next(g)) # 2
8 print(next(g)) # 3
9 print(next(g)) # 4
10
11 for x in g:
12 print(x) # 5, 6, 7, 8, 9, 10
13
14 # print(next(g)) # StopIteration
15
16
17 # 2、创建一个生成器对象, 包含1-10之间的所有偶数
18 g1 = (x for x in range(1, 11) if x % 2 == 0)
19
20 print(g1) # <generator object <genexpr> at 0x000000000260A948>
21 print(type(g1)) # <class 'generator'>
22
23 print(g1.__next__()) # 2
24 print(g1.__next__()) # 4
25 print(g1.__next__()) # 6
26 print(g1.__next__()) # 8
27 print(g1.__next__()) # 10
28
29 # print(g1.__next__()) # StopIteration
二、生成器函数
1、关键字yield 的作用
1、返回一个数据,如果yield后边啥也没有,返回数据为None
2、遇到yield获取一条数据,同时暂停函数的执行,直到下一次获取数据时,从暂停的位置继续往下执行
2、特点
1、生成器函数用来生成一个生成器对象
2、生成器函数中的代码在获取对象数据时,才会被执行
1 def func1():
2 print("我是生成器")
3 yield # return 返回值
4
5
6 g = func1()
7 print(g) # <generator object func1 at 0x0000000003C2CFC0>
8 print(type(g)) # <class 'generator'>
9
10 # 获取生成器对象数据的三种方式: 1, next(对象); 2,for..in 对象; 3. 对象.__next__()
11 print(next(g)) # 我是生成器 \n None
12
13
14 def func2():
15 print("我是生成器")
16 yield 0000
17
18
19 # step1: 获取生成器对象
20 g2 = func2()
21
22 # step2: 获取数据
23 print(g2.__next__())
24 """
25 我是生成器
26 0
27 """
28
29 # print(g2.__next__()) # StopIteration
30
31
32 def func3():
33 print("xixi")
34 yield "haha"
35 print("hanhan")
36 yield "daidai"
37
38
39 g3 = func3()
40
41 print(g3.__next__())
42 """
43 xixi
44 haha
45 """
46 print(g3.__next__()) # 三角龙
47 """
48 hanhan
49 daidai
50 """
51
52
53 def func4():
54 for x in range(10):
55 yield "我是第%d" % x
56
57
58 g4 = func4()
59
60 print(next(g4)) # 我是第0
61 print(next(g4)) # 我是第1
62 print(next(g4)) # 我是第2
63 print(next(g4)) # 我是第3
64
65
66 def func5():
67 print("我是第5个生成器函数")
68 child = yield "请给我xixi"
69 print("taotao&huihui")
70 yield child
71
72
73 g5 = func5()
74 # next(g5) # "请给我一只食肉龙"
75 print(g5.__next__()) # 1. 获取一个生成器的数据
76 """
77 我是第5个生成器函数
78 请给我xixi
79 """
80 # TypeError: can't send non-None value to a just-started generator
81
82 print(g5.send("haha")) # 2. 给生成器函数上一个yield的位置传递一个数据(霸王龙)
83 """
84 taotao&huihui
85 haha
86 """
87 # print(next(g5))
88 # print(g5.send("abc")) # StopIteration
三、生成器实例
1 # 1、传递数据, 计算所有传递的数据的总和,平均值
2 def func1():
3 sum_num = 0 # 用来记录所有数字的和, 初始值0
4 count = 0
5 avg = 0 # 用来记录所有数字的平均值, 初始值0
6 while True:
7 num = yield (sum_num, avg)
8 count += 1 # 每输入一个数据, 计数+1
9 sum_num += num # 每输入一个数据, 和累加
10 avg = sum_num / count
11
12 g1 = func1()
13
14 print(g1.__next__()) # (0, 0)
15 print(g1.send(5)) # (5, 5.0)
16 print(g1.send(10)) # (15, 7.5)
17 print(g1.send(100)) # (115, 38,33333333)
18
19 # 2、写一个生成器, 生成斐波那契数列;
20 # 1, 1, 2, 3, 5, 8, 13, 21, ...
21 # a b->2
22 # a b->3
23 def func2():
24 a = 1 # 所求数的前两个数
25 b = 1 # 所求数的前一个数
26 while True:
27 yield a # 1, 1, 2, 3, 5,...
28 a, b = b, a + b
29
30 g2 = func2()
31 print(g2.__next__()) # 1
32 print(g2.__next__()) # 1
33 print(g2.__next__()) # 2
34 print(g2.__next__()) # 3
35 print(g2.__next__()) # 5
36 print(g2.__next__()) # 8
37 print(g2.__next__()) # 11
四、为什么生成器是迭代器
1、概念
(1)可迭代对象: 实现了__iter__方法的对象就是可迭代对象
(2)迭代器: 实现了__iter__方法和__next__方法的对象就是迭代器
(3)生成器:函数中使用了关键字 yield
2、关联
(1)迭代器 是 可迭代对象
(2)生成器 是 可迭代对象
(3)生成器 是 迭代器
__iter__()方法的返回值是 迭代器
可迭代对象.__iter__(),就会生成一个 迭代器
3、判断对象是否可迭代
from collections.abc import Iterable
isinstance(对象,Iterable)
4、for in 的底层原理
for in 对象
(1)调用对象的__iter__()方法,生成一个iterator迭代器
(2)调用迭代器对象的__next__()方法,依次获取每个数据
(3)for in 在遇到 StopIteration 时,停止迭代
1 # 写个迭代器, 传入一个范围(起始值, 终止值), 依次获取
2 # 这个范围中的素数
3
4
5 class PrimeNumber:
6 def __init__(self, start, end):
7 self.start = start
8 self.end = end
9
10 # 方法: 判断一个数是不是素数
11 def isPrimeNumber(self, num): # 参数: 你要判断是不是素数的那个数
12 for x in range(2, num):
13 if num % x == 0:
14 return False # 返回, 函数停止执行
15 return True
16
17 def __iter__(self): # 返回个迭代器对象: generator(迭代器)--> __iter__(), __next__()
18 for x in range(self.start, self.end + 1):
19 if self.isPrimeNumber(x):
20 yield x
21
22 # yield --> 生成器函数(返回值:生成器) --> 迭代器 --> __iter__()方法返回个迭代器
23
24 n3 = PrimeNumber(3, 20)
25 for x in n3:
26 print(x)
27 """
28 3
29 5
30 7
31 11
32 13
33 17
34 19
35 """
36
37 # step1: 调用__iter__()获取迭代器 --> 生成器
38 # step2: 调用__next__()获取数据
39 # step3: StopIteration停止迭代
40
41 n4 = PrimeNumber(3, 20)
42 g4 = n4.__iter__()
43 print(g4.__next__()) # 3
1 g = (x for x in range(10))
2 print(g) # <generator object <genexpr> at 0x0000000003C2CFC0>
3 print(dir(g)) # 查看g的所有方法
4
5 def func():
6 yield "xixi"
7
8 g1 = func()
9 print(g1) # <generator object func at 0x000000000212A548>
10
11 print(g1.__next__()) # 'xixi'