• 生成器


    # 生成器函数
    # 只要含有 yield 关键字的函数都是生成器函数
    # yield 不能和 return 共用且需要写在函数内
    # 生成器函数:执行之后会得到一个生成器作为返回值
    # 生成器既含有 __next__ 方法,也含有 __iter__ 方法,所以生成器也是一个迭代器,可以使用 __next__ 方法获取下一个值,也可以通过 for 循环取值
    # yield和return一样,都可以返回一个值,但是 return 在返回值之后就直接结束一个函数,而 yield 不会
    def generator():
        '''含有yield,它是一个生成器函数'''
        print(1)
        yield 'a'
    
    
    ret = generator()
    print(ret)
    print(ret.__next__())
    '''
    <generator object generator at 0x02FCF8D0>
    1
    a
    '''

    # 如果我想生成2000000个哇哈哈,用生成器,每生成一个,就返回一个,这样就不会出现内存不足的问题
    def wahaha():
        for i in range(2000000):
            yield '哇哈哈%s' % i
    
    
    g = wahaha()
    for i in g:
        print(i)
    
    

    # send 获取下一个值的效果和 next 基本一致

    # 只是在获取下一个值的时候,给上一个 yield 的位置传递一个数据
    # 使用 send 的注意事项
    # 第一次使用生成器的时候 是用 next 获取下一个值
    # 最后一个 yield 不能接受外部的值
    
    
    def generator():
        print(123)
        content = yield 1
        print('=======', content)
        print(456)
        arg = yield 2
    
    
    g = generator()
    ret = g.__next__()
    print('***', ret)
    ret = g.send('hello')   # send的效果和next一样
    print('***', ret)
    '''
    123
    *** 1
    ======= hello
    456
    *** 2
    '''
     
    # 获取移动平均值
    # 10 20 30 10
    # 10 15 20 17.5
    # avg = sum/count
    def average():
        sum = 0
        count = 0
        avg = 0
        while True:
            num = yield avg
            sum += num    # 10
            count += 1    # 1
            avg = sum/count
    
    
    avg_g = average()
    avg_g.__next__()
    avg1 = avg_g.send(10)
    avg1 = avg_g.send(20)
    avg1 = avg_g.send(30)
    print(avg1)
    # 预激生成器的装饰器
    
    
    def init(func):   # 装饰器
        def inner(*args,**kwargs):
            g = func(*args,**kwargs)    # g = average()
            g.__next__()
            return g
        return inner
    
    
    @init
    def average():
        sum = 0
        count = 0
        avg = 0
        while True:
            num = yield avg
            sum += num    # 10
            count += 1    # 1
            avg = sum/count
    
    
    avg_g = average()   # ===> inner
    ret = avg_g.send(10)
    print(ret)
    ret = avg_g.send(20)
    print(ret)
    
    

    # python 3 新特性
    
    
    # python 2
    # def generator():
    #     a = 'abcde'
    #     b = '12345'
    #     for i in a:
    #         yield i
    #     for i in b:
    #         yield i
    
    
    # python 3
    def generator():
        a = 'abcde'
        b = '12345'
        yield from a
        yield from b
    
    
    g = generator()
    for i in g:
        print(i)
    '''
    a
    b
    c
    d
    e
    1
    2
    3
    4
    5
    '''
    
    

     

    # 生成器表达式

    # 列表推导式
    print([i*i for i in range(10)])
    # 生成器表达式
    print(i for i in range(10))
    '''
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    <generator object <genexpr> at 0x0120FAB0>
    '''

     # 生成器面试题

     # 面试题1

    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(g1)把g1当中所有的内容取出来
    print(list(g2))  # g1执行完之后已经空了,所以list(g2)为空列表
    '''
    [0, 1, 2, 3]
    []
    '''

    # 面试题2

    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)  # 从上到下,一直到这里,生成器都没有取过值
    '''相当于
    n = 1
    g = (add(n, i) for i in g)
    
    n = 10
    g = (add(n, i) for i in (add(n, i) for i in test()))
    这里,n = 10,而不是 n = 1,既
    g = (add(10, i) for i in (add(10, i) for i in [0, 1, 2, 3]))
    所以,最后结果为 [20, 21, 22, 23]
    '''
    
    print(list(g))  # 在这里,生成器才开始取值
    # [20, 21, 22, 23]
  • 相关阅读:
    要坚持的好习惯
    Attribute与Property关系
    浅谈ES6中super关键字
    JS权威指南读书笔记(七)
    JS权威指南读书笔记(六)
    JS权威指南读书笔记(五)
    JS权威指南读书笔记(四)
    函数
    对象
    数值
  • 原文地址:https://www.cnblogs.com/chuangming/p/9063369.html
Copyright © 2020-2023  润新知