美文网首页
Python---迭代器与生成器

Python---迭代器与生成器

作者: Wayne_Dream | 来源:发表于2018-12-02 15:54 被阅读16次

    1.迭代器(Iterator)

    可以直接作用于for循环的数据类型有以下几种:
    一类是集合数据类型,如list、tuple、dict、set、str等;
    一类是generator,包括生成器和带yield的generator function。
    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
    可以使用isinstance()判断一个对象是否是Iterable对象:

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False
    

    而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
    可以使用isinstance()判断一个对象是否是Iterator对象:

    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False
    生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
    把list、dict、str等Iterable变成Iterator可以使用iter()函数:
    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True
    

    你可能会问,为什么list、dict、str等数据类型不是Iterator?

    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    迭代器在类中的应用

    class fibs:
        def __init__(self, a, b):
            self.a = a
            self.b = b
        def __iter__(self):
            return self
    
        def __next__(self):
            self.a, self.b = self.b, self.a + self.b
            return self.b
    
    f = fibs(0, 1)
    

    建立了一个斐波那契数列的计算类,该类可以被迭代,需要获取前两个数值,调用next()便可以输出下一个斐波那契数。

    >>>f.__next__()
    1
    >>>f.__next__()
    2
    >>>f.__next__()
    3
    >>>f.__next__()
    5
    

    稍作修改,可以输出某个范围内的斐波那契数列:

    class fibs:
        def __init__(self, a, b, n):
            self.a = a
            self.b = b
            self.n = n
        def __iter__(self):
            return self
    
        def __next__(self):
            self.a, self.b = self.b, self.a + self.b
            if self.b < self.n:
                return self.b
            else:
                raise StopIteration
    
    f = fibs(0, 1, 100)
    for i in f:
        print(i)
    
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    

    2.生成器(generator)

    yield是生成器的灵魂,生成器是一种特殊的迭代器,是迭代器的一种实现,像使用迭代器需要定义一个类,来实现完整的功能,在生成器中,只需要使用yield,便可以实现函数的暂停与启用,就类似于单片机中的中断,使用起来更加方便。

    def Gen():
        yield print('生成器被调用1次')
        yield print('生成器被调用2次')
    mygen = Gen()
    
    >>>next(mygen)
    生成器被调用1次
    
    >>>next(mygen)
    生成器被调用2次
    
    >>>next(mygen)
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    StopIteration
    

    当一个生成器被执行next()时,会执行到yield的位置暂停,并返回yield后的内容,直到下一次执行next(),会从上一次暂停的位置继续执行,当没有元素可以执行时,会抛出一个StopIteration的异常,当然这和迭代器一样,可以使用for in来迭代

    >>>for i in mygen:
           pass
    
    生成器被调用1次
    生成器被调用2次
    

    同样,我们用生成器来实现一下斐波那契:

    def fibs(a, b, n):
        while True:
            a, b = b, a+b
            if b < n:
                yield print(b, end=' ')   #end=' '以空格为间隔输出b
            else:
                raise StopIteration
    
    for i in fibs(0,1,100):
        pass
    
    
    1 2 3 5 8 13 21 34 55 89
    

    是不是感觉比迭代器来的方便了呢!

    相关文章

      网友评论

          本文标题:Python---迭代器与生成器

          本文链接:https://www.haomeiwen.com/subject/vqmjcqtx.html