Python---迭代器与生成器

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 "", line 1, in 
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---迭代器与生成器)