7. 生成器类型

什么是可迭代对象

可迭代对象是指能用iter(iterable)函数返回迭代器的对象。

可迭代对象内部要定义__iter__(self)方法来返回迭代器对象。

示例

class MyIterable:
    def __iter__(self):
        语句块
        return 迭代器

什么是迭代器

是指能用next(iterator)函数取值的对象。

迭代器对象内部要定义 __next__(self)方法来返回当前取值,在没有值时需要引发StopIteration异常来终止迭代,即实现迭代器协议。

示例

class MyIterator:
    def __next__(self):
        迭代器协议
        return 数据

什么是生成器类

类内实现了 __iter__()__next__() 方法,并在 __next__ 方法内实现了迭代器协议,该类创建的对象够动态生成数据,这个类叫做生成器类。

python内置的range、enumerate和zip类就是生成器类。

生成器类创建的对象是可迭代对象,也是生成器对象。

生成器类的大致结构如下所示:

class MyGenerator:
    def __iter__(self):
        语句块
        return 迭代器
    def __next__(self):
        迭代器协议
        return 数据

生成器函数示例

仿照range()函数,写一个生成器类MyRange,替代 range函数的功能。

class MyRange:
    def __init__(self, start, stop=None, step=None):
    def __iter__(self):
    def __next__(self):

print(list(MyRange(5)))  # [0, 1, 2, 3, 4]
print(list(MyRange(5, 10)))  # [5, 6, 7, 8, 9]
print(list(MyRange(1, 10, 2)))  # [1, 3, 5, 7, 9]

实现代码

# 生成器类示例

# 仿照range()函数,写一个生成器类MyRange,替代 range函数的功能
class MyRange:
    def __init__(self, start, stop=None, step=None):
        # 1. 校正参数,得到开始值,结束值和步长
        if stop is None:
            stop = start
            start = 0
        if step is None:
            step = 1
        # 2. 判断开始值,结束值和步长是否都是整数,如果不是整数,则抛出TypeError异常
        if type(start) is not int:
            raise TypeError('start 不是整数!')
        if not isinstance(stop, int):
            raise TypeError('stop 不是整数!')
        if not isinstance(step, int):
            raise TypeError('step 不是整数!')
        self.start = start
        self.stop = stop
        self.step = step

    def __iter__(self):
        self.cur_value = self.start  # 初始化当前值
        return self  # 把自己当成迭代器返回

    def __next__(self):
        '''
        实现迭代器协议:
        生成整数并用送回给迭代器的next()函数,如果越界则引发StopIteration异常
        '''
        value = self.cur_value
        if self.step > 0:
            if self.cur_value >= self.stop:
                raise StopIteration
        if self.step < 0:
            if self.cur_value <= self.stop:
                raise StopIteration
        self.cur_value += self.step
        return value

print(list(MyRange(5)))  # [0, 1, 2, 3, 4]
print(list(MyRange(5, 10)))  # [5, 6, 7, 8, 9]
print(list(MyRange(1, 10, 2)))  # [1, 3, 5, 7, 9]
print(list(MyRange(10, 0, -2)))  # [10, 8, 6, 4, 2]

练习

写一个生成器类:Fibonacci 生成前n个斐波那契数列。

填写代码:

class Fibonacci:
    def __init__(self, n): ...  # 填写此方法的代码
    def __iter__(self):...  # 填写此方法的代码
    def __next__(self): ...  # 填写此方法的代码

fibonacci_list = list(Fibonacci(20))
print('前20个斐波那契数列:', fibonacci_list)