生成器的创建方式
(1)生成器的第一种创建方式
将列表生成式的中括号改成小括号
列表生成式
a = [x for x in range(0, 10)]
print(a)
结果为
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
生成器
b = (x for x in range(0, 10))
print(b)
结果为:
# 这就是一个生成器对象
<generator object <genexpr> at 0x0000000004C4F1A8>
(2)生成器的第二种方式
举个例子:斐波那契数列
def creatNum():
a, b = 0, 1
for i in range(0, 5):
print(b)
a, b = b, a+b
creatNum()
结果为
1
1
2
3
5
生成器形式
def creatNum():
a, b = 0, 1
for i in range(0, 5):
# 只要加了yield参数,该函数就成了生成器
yield b
a, b = b, a+b
# 创建了一个生成器对象
a = creatNum()
next(a) # 结果为:1
next(a) # 结果为:1
next(a) # 结果为:2
next(a) # 结果为:3
next(a) # 结果为:5
程序的执行过程
def creatNum():
print("---start---")
a, b = 0, 1
for i in range(0, 5):
print("---1---")
# 只要加了yield参数,该函数就成了生成器
yield b
print("---2---")
a, b = b, a+b
print("---3---")
print("---stop---")
a = creatNum()
next(a)
程序执行第一次调用next(a)的时候
print("---start---")
print("---1---")
1
程序第二次调用next(a)的时候
print("---2---")
print("---3---")
print("---1---")
1
程序第三次调用next(a)的时候
print("---2---")
print("---3---")
print("---1---")
2
程序第四次调用next(a)的时候
print("---2---")
print("---3---")
print("---1---")
3
程序第五次调用next(a)的时候
print("---2---")
print("---3---")
print("---1---")
5
程序第六次调用next(a)的时候
print("---2---")
print("---3---")
print("---stop---")
StopIteration
yield的作用
如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator.
generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
使用 for 循环来迭代:
生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停
利用for循环得到生成器数值
def creatNum():
a, b = 0, 1
for i in range(0, 5):
yield b
a, b = b, a+b
a = creatNum()
for num in a:
print(a)
结果为:
1
1
2
3
5
for循环的好处:生成器循环结束后,不会报错
send()函数
def test();
i = 0
while i <5:
temp = yield i
print(temp)
i += 1
t = text()
t.next()
程序第一次执行
0 # 返回yield的值
程序第二次执行
None # 程序从temp = yield i的左边执行,这时候因为yield i的值已经返回,所以temp的值为None
1
程序第三次执行
None # 跟第二次的结果一样
2
我们用send方法执行第四次
t.send("haha")
结果为
haha # send函数把"haha"赋值给了temp,所以把haha打印出来了
3
由此可见,send()方法和next()方法的区别为:
next()方法和send()方法都能返回一个生成器的值,只不过send方法能传一个值进去
send()方法不能作为第一次运行的方法或者写send(None)
send()方法里面的参数只能运行一次,再次运行需要重新赋值