zoukankan      html  css  js  c++  java
  • 生成器

    什么是生成器?

    生成器就是不在内存中一次性创建数据,而是在生成器使用过程中逐一创建,如果一个函数中有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))
    
  • 相关阅读:
    ie的bug及兼容性
    解决多次include后全局变量global失效的问题
    针对MYISAM表锁的解决方案(转)
    解决二进制文件冲突
    linux基本命令(1) 开关机操作
    子网掩码(NETMASK),ip地址,默认网关
    linux中常见设备对照表
    解决base64通过http传输后+变空格的问题
    mysql 查询某值是否存在于某结果集或表中
    laravel 报错 No query results for model
  • 原文地址:https://www.cnblogs.com/liuweida/p/11721856.html
Copyright © 2011-2022 走看看