专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

python中生成器的使用

python中我们常听到迭代器和生成器,但是本人分开来介绍,只为告诉大家迭代器和生成器不是一个东西,在上篇文章中我们详细的介绍过迭代器和可迭代对象,本章重点介绍生成器。

一、生成器的应用场景

对于调用一个普通的Python函数,一般是从函数的第一行代码开始执行,结束于return语句、异常或者函数所有语句执行完毕。一旦函数将控制权交还给调用者,就意味着全部结束。函数中做的所有工作以及保存在局部变量中的数据都将丢失。再次调用这个函数时,一切都将从头创建。Python是通过生成器来实现类似于协同程序的概念:生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。

二、一个最简单的生成器

  • 1、使用列表推导式的方式生成一个生成器
    from collections.abc import Iterator, Iterable

    if __name__ == "__main__":
        # 列表生成式
        lis = [x * x for x in range(10)]
        print(lis)
        print(isinstance(lis, Iterable))
        print(isinstance(lis, Iterator))

        # 生成器
        generator_ex = (x * x for x in range(10))
        print(generator_ex)
        print(isinstance(generator_ex, Iterable))
        print(isinstance(generator_ex, Iterator))
        print(next(generator_ex))

  • 2、从上面我们可以知道生成器是迭代器,具有迭代器的可迭代和**使用next()**函数的功能。记住:生成器是一种特殊的迭代器

三、为什么要使用生成器函数,而不是直接使用函数

  • 1、通过列表生成式可以直接创建一个列表,但是受到内存的限制,可能创建一个很大的空间,但是实际情况中用不到那么多(在C语言中所谓的堆区,没释放)
  • 2、生成器(generator)的定义就是根据列表元素可以动态的分配内存空间
  • 3、在实际开发过程中,如果我们要读取一个十几G大的文件,如果是直接使用文件打开的方式,其实底层的全部加载在内存中,这样造成计算机内存消耗,造成计算机卡死的局面,如果我们使用生成器,把大文件做成文档碎片的方式,每次从中间读取一点出来,然后再释放内存,这样就不会对计算机造成卡死的局面。

四、创建生成器函数

  • 1、将普通函数的return改为yield就是一个生成器函数
    def func():
        print('====>first')
        yield 1
        print('====>second')
        yield 2
        print('====>third')
        yield 3
        print('====>end')

    if __name__ == '__main__':
        g = func()
        print(g)
        # 生成器是一种特殊的迭代器,具有可迭代属性
        for item in g:
            print(item)

五、协同程序

协同程序(协程)一般来说是指这样的函数

  • 1、彼此间有不同的局部变量、指令指针,但是共享全局变量
  • 2、可以方便的挂起、恢复,并且有多个入口点和出口点
  • 3、多个协同程序间表现为协作运行,如A的运行过程中需要B的结果才能继续执行。

几个方法的介绍

  • 1、send(value):

    send()是除了next外另一个恢复生成器的方法,或者叫往生成器中传递参数的方法。是将yield语句变成了yield表达式,这意味着yield现在可以有一个值,而这个值就是在生成器的send方法被调用从而恢复执行时,调用send方法的参数。

    def test():
        i = 1
        while i < 5:
            temp = yield i ** 2
            print('temp', temp, '当前i=', i)
            i += 1

    if __name__ == "__main__":
        t = test()
        print(next(t))
        print(next(t))
        print(t.send('hello'))
        print(t.send('word'))

    # 运行结果
    1                           # 在main中打印的
    temp None 当前i= 1      # 在test函数中打印的
    4                           # 在main中打印的
    temp hello 当前i= 2     # 在test函数中打印的
    9                           # 在main中打印的
    temp word 当前i= 3      # 在test函数中打印的
    16                          # 在main中打印的

 *  调用`send`传入非`None`值前,生成器必须处于挂起状态,否则将抛出异常
 *  第一次调用`next`的时候 `yield 1**2`,返回是1,当时`temp`没有传递值是`None`
 *  第二次调用`next`的时候 `yield 2**2`返回是4,当时`temp`没有传递值是`None`
 *  第三次调用`send`发送数据,发送了`hello`当时`temp=word`,打印出`temp`的值,`yield 3**2`返回是9
 *  第四次和第三次一样的

* 2、close方法

这个方法用于关闭生成器。对关闭的生成器后再次调用`next`或`send`将抛出`StopIteration`异常

六、yield from的使用

yield fromPython3.3 后新加的语言结构。yield from的主要功能是打开双向通道,把最外层的调用方法与最内层的子生成器连接起来。这两者就可以进行发送值和返回值了,yeild from结构的本质是简化嵌套的生产器,不理解这个是什么意思的话,下面我将用几个例子来对其使用方法进行讲解

一般场景使用方式

def gene():
    for c in 'AB':
        yield c  # 遇到yeild程序返回循环,下次从yeild后面开始。
    for i in range(3):
        yield i

if __name__ == "__main__":
    print(list(gene()))  # list内部会预激生成器

使用yield..from的时候

def gene1():
    yield from 'ab'
    yield from range(3)

if __name__ == "__main__":
    print(list(gene1()))   

未经允许不得转载:搜云库技术团队 » python中生成器的使用

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们