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

    生成器是一类特殊的迭代器(既然是迭代器了,那么当然就是可迭代对象).自己就是.不需要写__iter__(),__next__()这两个方法.
    自己天生就是迭代器.
    仍然可以使用iter(),next() 方法.

    分类:
    列表推导式[]: ---> () 就是 生成器表达式 :():<generator:>

    生成器里面存放的不是具体的数据,只是存放的是一个算法.
    生成器表达式和列表推导式的异同:
    不同: (表达式) [表达式]
    -------------------|----------------------|---------------------
    产生的对象              生成器对象            列表对象
      占用内存                    少                          多
    -------------------|----------------------|---------------------
    相同: 使用结果一致

    方式1:生成器表达式 列表推导式的[] 换成()之后就是生成器
    首先要理解 列表推推导式 --> 返回值是一个列表

    方式2:生成器函数 含有yield 关键字

    def fib(n):
        num1, num2 = 1, 1
    
        count = 0
    
        # 1.暂时挂起当前函数  将后面的值返回给调用生成器的地方
        yield 100  # 返回值
        # 2.当再次调用生成器函数的时候, 会恢复当前函数继续执行
        yield 101  # 返回值
    
    
    if __name__ == '__main__':
        # 生成器函数调用   不会执行函数代码 唯一的目的就是:产生生成器对象
        f = fib(10)
    
        # 调用生成器<迭代器>,获取下一个元素的值
        print(next(f))
        print(next(f))
    
    # 断点调试只适用于少量代码的时候,多的时候不管用

    生成器计算斐波拉契:

    def fib(n):
        num1, num2 = 1, 1
        count = 0
        while count < n:
            yield num1  # 可以返回多个值  yield 1,2,3
            count += 1
            num1, num2 = num2, num1 + num2
        return 1000
    
    
    #  最后不需要raise StopIteration <生成器内部已经自动实现>
    # 一般在生成器中不使用return关键字,一旦使用就会结束生成器的迭代过程
    if __name__ == '__main__':
        f = fib(10)
        # for i in f:  可以取出多个值 for i,j in f:...
        #     print(i)
    
        # 如果需要获取生成器函数的最终返回值,需要捕获迭代的异常
        # while True:
        #     # 通过迭代器取出下一个元素的值<返回值>
        #     try:
        #         pass
        #     except Exception as e:
        #         print(e)
        #         break
        #     else:
        #         print(i)
    
    """send()唤醒生成器,可以传参数"""

    send在唤醒生成器的时候传入参数:

    """
    面试问:
    yield的作用:
    
    send()可以传参数,不能第一次使用
    
    使用场景:在生成下一个的时候,从我 指定的位置<传入的参数>开始生成
    通过传入的参数,控制生成器下一次生成的元素
    
    """
    """
    唤醒生成器:
    元素的值=next(生成器对象)
    元素的值=生成器.send(数据)
    
    异同:
        next是函数  send()是方法
        next不能传参数,send可以传入参数<通过传输不同的参数控制生成器执行的逻辑>
        第一次只能next,其余地方随意使用<参数的值只有yield可以接收,因为第一次的时候没有yield>
    同:
        获取到下一个元素的值<迭代>
    
    
    yield关键字作用:
        1.挂起当前函数代码,将后面的表达式返回,调用生成器的地方
        2.接收可能存在的参数,紧接着上次执行的地方继续往下执行
    
    """
    
    
    def fib(n):
        num1, num2 = 1, 1
        count = 0
        while count < n:
            # send()发送的消息只有yield关键字才能接收
            ret = yield num1
            print('接收到的参数是:', ret)
            count += 1
            num1, num2 = num2, num1 + num2
    
    
    if __name__ == '__main__':
        f = fib(10)
        # 在第一次调用生成器的时候必须使用next(),因为第一次的时候没有yield接收传入的参数
        # TypeError: can't send non-None value to a just-started generator
        # 意思就是不能在第一次的时候将非None的数据发送给生成器.
        # print(f.send(None))  这样就可以
        print(next(f))
        print(f.send(101))
        print(f.send(102))
        print(f.send(103))
        print(f.send(103))
        print(f.send(103))
    
    
    """
    容器类型就是典型的可迭代对象.
    
    典型的:意思就是通用的,肯定是,具有代表性的
    
    生成器肯定是可迭代对象.反之不行
    
    """
  • 相关阅读:
    Cocos2d-x之CCMenu理解
    【问题记录】mysql设置任意ip访问
    kafka eagle 使用教程
    查看Android源码和源码布局
    JAVA问题之泛型数组
    Linux面试题汇总答案(转)
    从源码看Azkaban作业流下发过程
    Azkaban源码学习笔记
    Java多线程基础学习(二)
    Java多线程基础学习(一)
  • 原文地址:https://www.cnblogs.com/huaibin/p/12100223.html
Copyright © 2011-2022 走看看