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

    在Python中, 一边循环一边计算后面元素的机制称为生成器 generator


    一、列表生成器

    语法:

     

    a = [i+1 for i in rang(10)]

    print(a)

    [1,2,3,4,5,6,7,8,9,10]


    二、生成器

    语法:

    把列表生成器中的中括号 [] 换成 () 即可

    例:

    (x*x for x in range(10))生成的就是一个生成器。

    如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

    generator保存的是算法,每次调用next(g)就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

    当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代(遍历)对象:

    >>> g = (x * x for x in range(10))

    >>> for n in g:

    ... print(n) ...

    0

    1

    4

    9

    16

    25

    36

    49

    64

    81


    三、函数生成器

    def feib(n):
    a = 0
    b = 1
    count = 0
    while count < n:
    tmp = a
    a = b
    b += tmp
    #print(b)
    yield b # 暂停,程序执行到这里,就会暂停到这里,返回b到函数外面,直到被next方法调用时才会唤醒
    count += 1
    f = feib(10) # 注意这句调用时,函数并不会被执行,只有下一次调用next方法时,函数才会真正被执行
    print(next(f))
    print(next(f))
    print("----暂停一下还能继续往下走----")
    print(next(f))

    四、并发编程
    通过yield, 我们可以实现单核下并发做多件事的效果
    例:
    def consumer(name):

    print("消费者%s准备吃包子了" % name)

    baozi = yield  # 此处的yield接收外部send传过来的数据并赋值给baozi

    print("消费者%S收到第%s批包子" %(name,baozi))

    c1 = consumer(c1)

    c2 = consumer(c2)

    c3 = consumer(c3)

    c1.__next()__   # 执行一下next才能使上面的函数走到yield那句,这样后面的send语法才能生效

    c2.__next()__

    c3.__next()__

    for i in range(1,10)

    print("-----生产了第%s批包子-----" % i )

    c1.send(i)  # send的作用=next,同时把数据i传给上面函数的yield

    c2.send(i)

    c3.send(i)

    输出结果:

    消费者c1准备吃包子了
    消费者c2准备吃包子了
    消费者c3准备吃包子了
    --------生产了第1批包子-------
    消费者c1收到第1批包子
    消费者c2收到第1批包子
    消费者c3收到第1批包子
    --------生产了第2批包子-------
    消费者c1收到第2批包子
    消费者c2收到第2批包子
    消费者c3收到第2批包子
    --------生产了第3批包子-------
    消费者c1收到第3批包子
    消费者c2收到第3批包子
    消费者c3收到第3批包子
    --------生产了第4批包子-------
    消费者c1收到第4批包子
    消费者c2收到第4批包子
    消费者c3收到第4批包子
    --------生产了第5批包子-------
    消费者c1收到第5批包子
    消费者c2收到第5批包子
    消费者c3收到第5批包子
    --------生产了第6批包子-------
    消费者c1收到第6批包子
    消费者c2收到第6批包子
    消费者c3收到第6批包子
    --------生产了第7批包子-------
    消费者c1收到第7批包子
    消费者c2收到第7批包子
    消费者c3收到第7批包子
    --------生产了第8批包子-------
    消费者c1收到第8批包子
    消费者c2收到第8批包子
    消费者c3收到第8批包子
    --------生产了第9批包子-------
    消费者c1收到第9批包子
    消费者c2收到第9批包子
    消费者c3收到第9批包子

    注意:调用send(x)给生成器传值时,必须确保生成器已经执行过一次next()调用, 这样会让程序走到yield位置等待外部第2次调用。

  • 相关阅读:
    R因子、聚类
    R语言存储
    JavaScript跨域实现
    大型项目工程代码快速上手指北
    Mac环境MySql初始密码设置
    Entity Framework基础—第六篇(Code First)
    Entity Framework基础—第五篇(Model First两种延迟加载)
    Entity Framework基础—第四篇(Model First)
    Entity Framework基础-第三篇
    Entity Framework基础—第二篇
  • 原文地址:https://www.cnblogs.com/nanjo4373977/p/12023113.html
Copyright © 2011-2022 走看看