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

    本文通过文章同步功能推送至博客园,显示排版可能会有所错误,请见谅!

    一、初识生成器

    生成器可以理解一种自动实现迭代器协议的数据类型,所以生成器本身就是一个迭代器

    区别于列表、元组、字符串等可迭代对象,生成器无需调用__iter__()方法直接就能使用next方法进行迭代

    生成器有两种定义方法

    1.定义一个函数。用yield替代return,调用函数时,当运行到yield时,返回一个值同时函数暂停,直到下一次调用函数,返回下一个yield或Stopitertion错误

    2.生成器表达式。区别于列表解析式,列表解析式使用[]定义,一经生成,直接读入内存。而生成器表达式只有在实际调用时才会读入内存,使用()定义,优势是内存占用小,效率高。

    二、生成器优化

    生成器相比于列表解析式,有几个优点:

    1.占用内存小,几乎不占内存

    2.只有在使用next时,才会返回值

    3.next之前的值都会被python删除(即占用内存小的原因)

    """使用列表情况"""
    import time
    t0 = time.time()
    def make_baozi(n):
        """制造n个包子并返回"""
        return ["包子%s" % i for i in range(1,n+1)]
    def chi_baozi(*args):
        '''给我多少个包子我就吃多少个'''
        for i,x in enumerate(args):
            print('第%d个客人吃了%s' % (i+1,x))
    chi_baozi(*make_baozi(5000000))
    

    全程耗时45.34496521949768秒

    此时Python占用内存高达547M且与生产包子数表现出明显正相关

    '''生成器优化'''
    def make_baozi(n):
        for i in range(1,n+1):
            yield '包子%d' %i
    def chi_baozi(x):
        print('客人吃了%s' % x)
    mb = make_baozi(5000000)
    while True:
        try:
            chi_baozi(mb.__next__())
        except StopIteration:
            break

    全程耗时47.534424781799316秒

    此时Python全程占用内存6.2M  且内存占用与生产包子个数不相关

    上述代码为测试使用列表解析式和生成器表达式的相关占用区别,可以看出来,生成器几乎不占内存,对于大数据处理内存优化提升十分明显。在这个模拟程序中,总耗时并无显著区别,主要取决于cpu处理速度。但是对于单个用户体验来说,整体有所提升(客人吃到包子1的时间明显提前了,而吃到最后一个包子时间则相差无几)。

    三、更多

    Python由于全局锁(GIT)的存在,其并发效率低一直受人诟病,而Python的多线程和多进程也存在不少问题并非很好的解决方案,Python开发社区逐渐将视野转到协程上来,通过多线程/多线程再辅以协程可以提高并发效率,而协程主要基于生成器来实现。关于生成器与协程,请听下回分解。

  • 相关阅读:
    cookie的使用
    给定一个数组和一个目标值,找出和为目标值的整数,并返回他们的下标
    String详解
    阳哥讲面试题(四)生产调优
    springboot项目调优(针对特性的服务启动,定制化诉求)
    intern() 方法
    阳哥讲面试题(四)OOM,GC算法,垃圾收集器
    阳哥讲面试题(三)JVM,GC
    阳哥讲面试题(二)队列,线程池
    Semaphore用法
  • 原文地址:https://www.cnblogs.com/lazyfish007/p/11487617.html
Copyright © 2011-2022 走看看