• [ Python ] 迭代对象、迭代器、生成器


    1. 容器(container)

    容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个的迭代获取,可以用 in / not in 关键字判断元素是否包含在容器中。通常这类数据结构把所有元素存储在内存中。比如:list, set, tuples都是容器对象

    >>> 1 in [1, 2, 3]
    True
    >>> 4 not in [1,2,3]
    True
    >>> 1 in (1,2,3)
    True
    >>> 4 not in (1,2,3)
    True
    >>> 1 in {1,2,3}
    True
    >>> 4 not in {1,2,3}
    True
    

    2. 可迭代对象(iterable)

    什么的迭代?
        迭代就是可以被 for 循环遍历, 在python中一切皆对象,可以被 for 循环迭代的对象就叫 可迭代对象;

    >>> for i in [1,2,3]:
    ...     print(i)
    ...
    1
    2
    3
    >>> for i in (1,2,3):
    ...     print(i)
    ...
    1
    2
    3
    >>> for i in {'a': 1, 'b': 2, 'c': 3}:
    ...     print(i)
    ...
    a
    c
    b
    

     可迭代对象并不是指某种具体的数据类型,list 是可迭代对象,dict是可迭代对象,set也是可迭代对象。

    3. 迭代器(iterator)

    可迭代对象是实现了 __iter__() 方法的对象,而迭代器(iterator)则是实现了 __iter__() 和 __next()__ 方法的对象,可以显示的获取下一个元素,这种可以被 next 调用并不断返回下一个值的对象称为迭代器;

    iterator是一个带状态的对象,能在调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()方法的对象都是迭代器
    __iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多的元素了,则抛出StopIteration异常。所以迭代器是每次询问要下一个值的时候返回

    迭代器一定是可迭代对象,反过来则不一定成立。

    >>> l1 = ['a', 'b', 'c']
    >>> l_iter = l1.__iter__()
    # 可迭代对象通过调用 __iter__方法生成一个迭代器
    >>> l_iter
    <list_iterator object at 0x000001EA16975710>
    # 迭代器通过 __next__方法返回一个值
    >>> l_iter.__next__()
    'a'
    >>> l_iter.__next__()
    'b'
    >>> l_iter.__next__()
    'c'
    >>> l_iter.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

     迭代器是一个惰性的计算,等到有人调用的时候才返回值,没调用的时候就处于休眠状态等待下一次调用。

    4. 生成器(generator)

    generator 是一种数据类型,这种数据类型自动实现了迭代器协议,所以生成器就是可迭代对象;
    生成器一定是迭代器,反之则不成立。
    当在内存中存储一个很大的列表时,需要消耗大量的内存,如果列表元素可以按照某种算法推算出来,那我们就可以通过循环的过程不断推算出后续的元素,这样就不必创建完成的list, 从而节约了大量的空间。在python中,这种一边循环一边计算的机制,称为生成器(generator)

    创建一个生成器有两种方式:

    (1)把一个列表生成式的[]改成()

    >>> l1 = ['a', 'b', 'c']
    >>> l = [x for x in range(10)]
    >>> l
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> g = (x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x000001EA16972308>	
    

     
    (2)通过yield 关键字

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a + b
            n += 1
    
    
    f = fib(5)
    print(list(f))
    
    # 执行结果:
    # [1, 1, 2, 3, 5]
    

    fib就是一个普通的python函数,特殊的地方在于函数体中没有 return关键字,函数的返回值是一个生成器对象。此时函数体中的代码并不会执行,保存的是一个算法。
    可以通过遍历迭代器的方式来遍历生成器。

    5. 总结

     (1)容器是一系列元素的集合:str, list, set, dict, file, sockets对象都可以看做容器,容器是可以被迭代的,因此他们称为可迭代对象
        (2)可迭代对象实现了__iter__方法,该方法返回一个迭代器对象
        (3)迭代器持有一个内部状态的字段,用于记录下一次迭代返回值,它实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候返回结果。
        (4)生成器是一种特殊的迭代器,它的返回值不是通过return而是通过yield.

  • 相关阅读:
    Filter 和 interceptor 的区别
    JAVA基础知识|Optional
    CentOS 7安装MariaDB 10详解以及相关配置
    Linux系统zookeeper环境搭建(单机、伪分布式、分布式)
    Java设计模式——模板方法模式
    Java设计模式——装饰模式
    Java设计模式——观察者模式
    Java设计模式——代理模式
    Java设计模式——适配器模式
    Java设计模式——策略模式
  • 原文地址:https://www.cnblogs.com/hukey/p/9254950.html
Copyright © 2020-2023  润新知