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

    本文援引自:http://www.cnblogs.com/smallmars/p/6939519.html

    1.定义

    生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。

    也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。

    yield的功能:
    1.相当于为函数封装好__iter__和__next__
    2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行

    例:

    复制代码
    def counter(n):
        print('start...')
        i=0
        while i < n:
            yield i
            i+=1
        print('end...')
    
    
    g=counter(5)
    print(g)
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    # print(next(g))   #会报错
    复制代码

    输出

    start...
    0
    1
    2
    3
    4

     

    2.生成器函数

    • 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行;

    普通函数return返回

    复制代码
    def lay_eggs(num):
        egg_list=[]
        for egg in range(num):
            egg_list.append('蛋%s' %egg)
        return egg_list
    
    yikuangdan=lay_eggs(10) #我们拿到的是蛋
    print(yikuangdan)
    复制代码

    输出

    ['蛋0', '蛋1', '蛋2', '蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

    迭代器函数

    复制代码
    def lay_eggs(num):
        for egg in range(num):
            res='蛋%s' %egg
            yield res       #生成器关键语法
            print('下完一个蛋')
    
    laomuji=lay_eggs(10) #我们拿到的是一只母鸡
    print(laomuji)
    print(laomuji.__next__())       #迭代  蛋0
    print(laomuji.__next__())     #蛋1
    print(laomuji.__next__())       #蛋2
    egg_l=list(laomuji)
    print(egg_l)
    复制代码

    输出

    复制代码
    蛋0
    下完一个蛋
    蛋1
    下完一个蛋
    蛋2
    下完一个蛋
    下完一个蛋
    下完一个蛋
    下完一个蛋
    下完一个蛋
    下完一个蛋
    下完一个蛋
    下完一个蛋
    ['蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']
    复制代码

    3.生成器表达式

    • 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表;
    • food=yield food_list

      #g.send('food1'),先把food1传给yield,由yield赋值给food,然后返回给food_list,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回给food_list

    注意:开始生成器不能send非空值

    复制代码
    def eater(name):        #协程函数
        print('%s ready to eat' %name)
        food_list=[]
        while True:
            food=yield food_list           #装饰器表达式
            food_list.append(food)
            print('%s start to eat %s' %(name,food))
    
    
    g=eater('hexin')
    print(g)        #生成器

    print(g.send('food1')) #传值
    复制代码

    输出

    Traceback (most recent call last):
    <generator object eater at 0x1049030f8>    #生成器对象
      File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in <module>
        print(g.send('food1'))
    TypeError: can't send non-None value to a just-started generator    #开始生成器不能send非空值
    • 初始化后
    复制代码
    def eater(name):        #协程函数
        print('%s ready to eat' %name)
        food_list=[]
        while True:
            food=yield food_list           #装饰器表达式
            food_list.append(food)
            print('%s start to eat %s' %(name,food))
    
    
    g=eater('hexin')
    print(g)        #生成器
    next(g) #等同于 g.send(None),初始化
    
    print(g.send('food1'))
    复制代码

    输出

    <generator object eater at 0x107cde258>
    hexin ready to eat
    hexin start to eat food1
    ['food1']
    • 为了防止忘记初始化,可利用装饰器进行初始化,如下
    复制代码
    def deco(func):     #初始化函数
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            next(res)          #等同于 g.send(None),初始化
            return res
        return wrapper
    
    @deco       #用初始化函数装饰器,调用初始化函数
    def eater(name):        #协程函数
        print('%s ready to eat' %name)
        food_list=[]
        while True:
            food=yield food_list           #装饰器表达式
            food_list.append(food)
            print('%s start to eat %s' %(name,food))
    
    
    g=eater('hexin')
    # print(g)        #生成器
    # next(g) #等同于 g.send(None),初始化
    
    print(g.send('food1'))
    print(g.send('food2'))
    print(g.send('food3'))
    复制代码

    输出

    复制代码
    hexin ready to eat
    hexin start to eat food1
    ['food1']
    hexin start to eat food2
    ['food1', 'food2']
    hexin start to eat food3
    ['food1', 'food2', 'food3']
    复制代码
  • 相关阅读:
    五种实用DOM方法总结
    九月工作总结
    八月下半月工作总结
    【工作总结】七月底-八月中
    权限管理功能的实现
    JavaWeb项目出现红色感叹号
    项目中遇到的AngularJs问题
    五月工作总结
    生成流水号的优化
    AngularJS scope 作用域的问题
  • 原文地址:https://www.cnblogs.com/saintdingspage/p/9101711.html
Copyright © 2011-2022 走看看