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

    #在了解生成器之前,可以先看看一个名为"列表生成式"的东西

    list = [ x*2 for x in range(0,9) ]
    print(list)
    print(type(list))
    
    ########
    [0, 2, 4, 6, 8, 10, 12, 14, 16]
    <class 'list'>

    #由名字可知,列表生成式的作用就是生成一个列表,规则是: [ f(x) for x in 序列 ]

    #但是,列表声称式会将生成的列表直接放入内存中,当数据较大时不适用

    #所以就有了生成器

    #生成器的第一种创建方法:( f(x) for x in 序列 )

    s1 = ( x*3 for x in range(0,3) )
    print(s1)
    
    ########
    <generator object <genexpr> at 0x0000000001E8C518>

    #发现直接打印s1无法获取其中的信息,输出的是 生成器对象和其地址

    #这就是生成器与列表生成式的区别所在,生成器不会直接将所有数据放入内存中,而是作为一个对象返回

    #当需要使用时,通过next()方法调用

    print(next(s1))
    print(next(s1))
    print(next(s1))
    print(next(s1))
    
    ########
    0
    3
    6
    Traceback (most recent call last):
      File "E:/9--python/python_project/test.py", line 25, in <module>
        print(next(s1))
    StopIteration

    #生成器在创建时就已经确定了其数据量,调用的次数就已经确定,如果超过生成器的数据量的调用就会有  StopIteration  的报错,此报错在for循环中会用到,当然这是后话

    #由此可见,生成器占用的内存仅为保存对象地址,在调用时才生成值

    #第一种生成器的创建比较粗旷,另外一种生成器的创建则可定义的内容较多

    def foo():
        print("ok1")
        yield 2
        print("ok2")
        yield 5
    s2=foo()
    print(s2)
    print(next(s2))
    print(next(s2))
    print(next(s2))
    
    ########
    <generator object foo at 0x00000000027CC518>
    ok1
    2
    ok2
    5
    Traceback (most recent call last):
      File "E:/9--python/python_project/test.py", line 37, in <module>
        print(next(s2))
    StopIteration

    #生成器也算是函数的另一变种,一个yield就可以迭代一次,yield的返回值同return一样可以用参数接收

    #在yield中,自动封装了next()方法,使得我们可以优雅的调用

    #next()方法的路径是:

    1.第一个next(s1),进入foo()函数体,遇到print("ok1"),输出

    2.向下执行代码,遇到yield 2,返回指定值2,退出,状态保存在此,待下一个next()执行来调用

    3.第二个next(s2),进入foo()函数体,从yield 2开始,向下执行代码,遇到print("ok2"),输出

    4.向下执行代码,遇到yield 5,返回指定值5,退出,状态保存在此,待下一个next()执行来调用

    5.第三个next(s3),进入foo()函数体,从yield 5开始,向下执行代码,因为没有yield,报错

    #从以上可知,生成器的代码不会一次性执行完,而是遇到yield就退出,并将状态保存,待下次执行时调用,这个是实现协程的基础

    #生成器除了next()方法外,还有一个可以传入参数的方法:generator.send()

    def bar():
        count1 = yield 5
        print(count1)
        count2 = yield 1
        print(count2)
    s3=bar()
    ret1=s3.send(None)
    print(ret1)
    ret2=s3.send(2)
    print(ret2)
    ret3=s3.send(6)
    print(ret3)
    
    ########
    5
    2
    1
    6
    Traceback (most recent call last):
      File "E:/9--python/python_project/test.py", line 52, in <module>
        ret3=s3.send(6)
    StopIteration

    #generator.send()方法可以向生成器传入参数,但第一次因为还没有进入函数体,所以也不知道传递给那个参数,所以第一次使用send()方法时不能传入值,generator.send(None)=next(generator)

    #当下一次使用send(var)方法传入值时,会进入上次退出的位置,将值传给此处预先定义的参数,向下执行代码,直到下一个yield,保存状态,退出

  • 相关阅读:
    vue路由
    vue-cli目录结构介绍
    andriodiphone视频禁止全屏播放
    JS判断Android、iOS或浏览器的多种方法(四种方法)
    vue中移动端自适应方案
    移动端视频不兼容
    vue之router-link
    移动端网页开发注意点
    AWS EC2服务器的HTTPS负载均衡器配置过程
    Kubernetes概念介绍和v1版本部署过程
  • 原文地址:https://www.cnblogs.com/jianbonet/p/8657568.html
Copyright © 2011-2022 走看看