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

    生成器generator

    • 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象

    生成器函数

    • 函数体中包含yield语句的函数,返回生成器对象
    • 生成器对象,是一个可迭代对象,是一个迭代器
    • 生成器对象,是延迟计算,惰性求值

    举例:

    def inc():
        for i in range(5):
            yield i
    print(type(inc))  #函数类型  #<class 'function'>
    print(type(inc()))  #生成器类型 #<class 'generator'>
    x = inc()
    print(type(x))
    print(type(next(x)))
    for m in x :
        print(m,'*')
    for m in x :
        print(m, '**')
    
    """
    #执行结果
    <class 'function'>
    <class 'generator'>
    <class 'generator'>
    <class 'int'>
    1 *
    2 *
    3 *
    4 *
    """
    y = (i for i in range(5))
    print(type(y))
    print(next(y))
    print(next(y))
    #执行结果
    <class 'generator'>
    0
    1
    • 普通函数调用fn(),函数会立即执行完毕,但是生成器函数可以使用next函数多次执行。
    • 生成器函数等价于生成器表达式,只不过生成器函数可以更加的复杂
    def gen():
        print('line 1')
        yield 1
        print('line 2')
        yield 2
        print('line 3')
        yield 3
    
    next(gen())
    next(gen())
    g = gen()
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g,'End'))
    • 在生成器函数中,使用多个yield语句,执行一次后会暂停执行,把yield表达式的值返回
    • 再次执行会执行到下一个yield语句
    • return 语句依然可以终止函数运行,但return语句的返回值不能被获取
    • return会导致无法继续获取下一个值,抛出异常StopIteration
    • 如果函数没有显示的return语句,如果生成器函数执行到结尾,一样会抛出异常StopIteration异常

    生成器函数总结:

    • 包含yield语句的生成器函数生成生成器对象的时候,生成器函数的函数体不会立即执行
    • next(generator)会从函数的当前位置后执行到之后碰到的第一个yield语句,会弹出值,并暂停函数执行
    • 再次调用next函数,和上一条一样的处理过程
    • 没有多余的yield语句能被执行,继续调用next函数,会抛出异常StopIteration异常

    计数器:

    def inc():
        def counter():
            i=0
            while True:
                i += 1
                yield i
        c = counter()
        return lambda : next(c)
    foo = inc()
    print(foo())
    print(foo())
    print(foo())
    • lambda 表达式是匿名函数
    • return 返回一个匿名函数

    生成器处理递归问题:

    def fib():
        x = 0
        y = 1
        while True:
            yield y
            x,y=y,x+y
    foo = fib()
    # for _ in range(5):
    #     print(next(foo))
    # for _ in range(100):
    #     print(next(foo))
    print(next(foo))

    协程coroutine

    • 生成器的高级用法
    • 比进程、线程轻量级
    • 是用户空间调度函数的一种实现
    • Python3 asyncio 就是协程实现,已经加入到标准库
    • Python3.5 async  await 关键字直接原生支持协程
    • 协程调度器实现思路:
      • 有2个生成器A、B
      • next(a)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,然后再次调用next(A),再调用next(B)在,周而复始,就实现了调度的效果
      • 可以引入调度的策略来实现切换的方式
    • 协程是一种非抢占式调度

    yield from

    • yield from是Python 3.3出现的新的语法
    • yield from iterable 是 for item in iterable: yield item 形式的语法糖
      • 从可迭代对象中一个一个拿元素
    def conuter(n):
        for x in range(n):
            yield x
    def inc(n):
        yield from conuter(n)
    foo = inc(10)
    print(next(foo))
    print(next(foo))
    print(next(foo))
  • 相关阅读:
    C# WinForm判断Win7下程序是否以管理员身份运行
    C#设置文件(夹)权限
    验证字符串是否为有效的IP地址
    内存对齐
    C#线程启动时传入参数
    写字符串内容到文件
    Thread.Abort() Is Evil.
    如何优雅地控制线程状态
    C#读取文件,返回字符串形式的文件内容
    关于产生不重复随机数的算法 C#
  • 原文地址:https://www.cnblogs.com/xzkzzz/p/11353036.html
Copyright © 2011-2022 走看看