生成器

什么是生成器?

生成器就是不在内存中一次性创建数据,而是在生成器使用过程中逐一创建,如果一个函数中有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))
posted @ 2019-10-22 19:07  Lowell  阅读(160)  评论(0编辑  收藏  举报