生成器
什么是生成器?
生成器就是不在内存中一次性创建数据,而是在生成器使用过程中逐一创建,如果一个函数中有yield关键字,那么该函数就是生成器函数。
生成器的特点
只有在循环迭代时才正常执行函数内部代码 , 不循环的状态下不执行,如下示例
def func():
print("进入生成器函数")
for i in range(5):
yield i
# 此时并没有执行func()这个生成器函数
f = func()
# 此时才会进入生成器函数执行内部代码,list不容易理解分析的话可以使用for循环
#print(list(f))
for i in f:
print(i)
# 可以通过断点查看代码执行流程
生成器只能被迭代执行一次,如:for循环取值或者list取值,示例如下
def func():
for i in range(5):
yield i
f = func()
a = list(f)
print(a) # [0, 1, 2, 3, 4]
b = list(f)
print(b) # []
生成器函数如果使用next()或者send()从生成器中取值时,每执行完一次之后,它又会寻觅下一个yield进行等待,如果找不到,就会报错StopIteration。示例如下:
def func():
for i in range(5):
yield i
if i == 3:
break
f = func()
for m in range(5):
next(f)
def func():
for i in range(5):
yield i
if i == 3:
break
f = func()
f.send(None) # 使用next(f)一样
for m in range(5):
f.send(m)
- 生成器中的两个方法
- next():取出生成器中的值,每执行一次取出一个,并继续执行yeild之后的代码。
- send():
- 和next()相似,每执行一次取出一个,next()等于send(None)
- 和next()不同点,send()要传一个参数,且第一次执行只能传None,之后再传的参数会赋值到yield,
并传回。即赋值给下面代码的v。
def demo():
for i in range(4):
v = yield i
print(v)
g = demo()
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# 输出结果:
"""
0
None
1
None
2
None
3
"""
print(g.send(None))
print(g.send(5))
print(g.send(10))
print(g.send(15))
"""
0
5
1
10
2
15
3
"""
生成器的示例
如有需要,简单分析在后面
生成器示例一
def demo():
for i in range(4):
yield i
g = demo()
g1 = (i for i in g)
g2 = (i for i in g1)
print(list(g1))
print(list(g2))
生成器示例二
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g = test()
for n in [1,10]:
g = (add(n,i) for i in g)
print(list(g))
print(list(g))
print(list(g))
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g = test()
for n in [1,10,5]:
g = (add(n,i) for i in g) # 循环三次并不会执行生成器,但是g会被一遍一遍的重新赋值
# 循环第一次是 g = (add(n,i) for i in test())
# 循环第二次是 g = (add(n,i) for i in (add(n,i) for i in test()))
# 循环第三次是 g = (add(n,i) for i in (add(n,i) for i in (add(n,i) for i in test())))
print(list(g))
print(list(g))
print(list(g))
print(list(g))
示例一分析
def demo():
for i in range(4):
yield i
g = demo()
g1 = (i for i in g)
g2 = (i for i in g1)
print(list(g1))
# 只有list以后才开始执行,之前都不执行,
# 此时[0,1,2,3],g1再循环取值或list取值已经无法取到,
# 生成器只能执行一次
for n in g1: # g1是空的取不到值了
print(n)
print(list(g2))
示例二分析
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g = test()
# for n in [1,10,5]:
# n = 1
# g = (add(n,i) for i in test())
# n = 10
# g = (add(n,i) for i in (add(n,i) for i in test()))
n = 5
# 可以将上面的循环变更成下面的方式
g = (add(n,i) for i in (add(n,i) for i in (add(n,i) for i in test())))
print(list(g))
print(list(g))