zoukankan      html  css  js  c++  java
  • Python生成器和迭代器

    1、什么是生成器

    要说生成器,那就要先看列表,有了列表为啥还要生产器呢。列表可以写成解析式,书写简单,运行速度快,但是列表是一次性生成全部数据,如果数据较大就需要很大的内存。

    >>> a=[i*i for i in range(10)]
    >> a
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    列表a需要一次把全部数据生成出来,如果数据成千上万就会受限制。

    如果列表元素不是一次性全部生成,而是在循环中不断的计算推导出来,那就不需要一次创建列表数组,不需要申请很大的内存空间,这就是生成器。

    2、生成器的特点

    上面的列表推导式的方括号改为圆括号,就是生成器。

    >>> a=(i*i for i in range(10))
    >>> a
    <generator object <genexpr> at 0x00000224FFB4DB48>

    那么怎么从生成器里取数据呢?

    >>> next(a)
    0
    >>> next(a)
    1
    >>> next(a)
    4
    >>> next(a)
    9
    >>> next(a)
    16
    >>> next(a)
    25

    生成器generator有一个next方法,每次调用都会计算出他的下一个元素的值。生成器是可以迭代的,所以可以直接使用for语句循环生成器。

    >>> a=[i*i for i in range(10)]
    >>> for i in a:
        print(i, end=' ')    
    >>> 0 1 4 9 16 25 36 49 64 81

    除了使用圆括号创建生成器,也可以用yeild创建生成器,含有yeild关键字的函数都是生成器。生成器其实是一种特殊的迭代器,但是不需要像迭代器一样实现__iter__和__next__方法,只需要使用关键字yield就可以。

    def gen_squares(num):
        for x in range(num):
            print("x0=",x)
            yield x ** 2
            print("x1=",x)

    调用生成器:

    for i in gen_squares(5):
        print(i)

    输出如下,开始x=0,先输出x0=0,然后yeild返回print(i)打印平方数。下次循环回到yeild位置执行输出x1=1,然后循环x=1,输出x0=1,再次yeild到print(i)。

    x0= 0
    0
    x1= 0
    x0= 1
    1
    x1= 1
    x0= 2
    4
    x1= 2
    x0= 3
    9
    x1= 3
    x0= 4
    16
    x1= 4

    调用部分做个简单修改:

    for i in gen_squares(5):
        print(i)
        if i==1:
            break

    输出为如下,可见yield能保存内部状态,并挂起中断退出。在下一轮迭代调用时,从yield的地方继续执行,并且沿用上一轮的函数内部变量的状态,直到内部循环过程结束。

    x0= 0
    0
    x1= 0
    x0= 1
    1

    python使用生成器对延迟操作提供了支持,需要时才计算,不提前计算,这种做法节约内存空间,但是需要一直调用计算过程,可以说是时间换空间吧。

    3、什么是迭代器

    实现了__iter__和__next__方法的对象都称为迭代器。迭代器完成迭代功能,基于上一次的结果重复计算,自动记录所在的位置,而不需要手动记录索引,含有__iter__方法的对象都是可迭代对象。

    迭代对象内置两个方法:__next__和__iter__方法。next方法可以使迭代器自动记录迭代位置而不需要用户维护索引。iter方法能返回迭代器本身。

    迭代器是一个有状态的对象,在调用next() 的时候返回下一个值,如果容器中没有更多元素了,则抛出StopIteration异常。

    列表、元组就实现了迭代器。

    >>> a=[1,2,3,4]
    >>> it = a.__iter__()
    >>> next(it)
    1
    >>> next(it)
    2
    >>> next(it)
    3
    >>> next(it)
    4
    >>> next(it)
    Traceback (most recent call last):
      File "<pyshell#547>", line 1, in <module>
        next(it)
    StopIteration

    4、实现迭代对象

    class square:
        def __init__(self, n):
            self.prev = 0
            self.curr = 0
            self.n = n
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if(self.curr < self.n):
                self.prv = self.curr * self.curr
                self.curr+=1
                return self.prv
            else:
                 raise StopIteration
    
    a
    = square(10) for i in a: print(i) print(" ------- ") b = square(5) for i in b: print(i)

    输出结果为:

    ==================== RESTART: C:/Users/plu/my_python/t1.py ====================
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
     
    ------- 
    
    0
    1
    4
    9
    16
    >>>
  • 相关阅读:
    Linux基操:软件安装的方式:解压缩安装
    Linux基操:linux命令失效解决方法
    Linux基操:软件安装的方式:rpm,&&环境变量配置
    Linux基操:进程管理
    Linux基操:磁盘管理,扩展文件挂载问题
    Linux基操(Centos7):用户管理
    Linux基操:文件内容查看方式&&软链接硬链接(拓展)
    Linux基操:目录相关命令
    多测师肖sir_高级金牌讲师__面试和答案归纳
    多测师肖sir__高级金牌讲师 ___python中len函数
  • 原文地址:https://www.cnblogs.com/pingwen/p/12634692.html
Copyright © 2011-2022 走看看