7. 生成器类型
什么是可迭代对象
可迭代对象是指能用iter(iterable)函数返回迭代器的对象。
可迭代对象内部要定义__iter__(self)方法来返回迭代器对象。
- iter(iterable) 函数调用的就是对象的obj.iter()方法。
示例
class MyIterable:
def __iter__(self):
语句块
return 迭代器
什么是迭代器
是指能用next(iterator)函数取值的对象。
迭代器对象内部要定义 __next__(self)
方法来返回当前取值,在没有值时需要引发StopIteration异常来终止迭代,即实现迭代器协议。
- next(iterator) 函数调用的就是对象的
obj.__next__()
方法。
示例
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个斐波那契数列。
- 斐波那契数列的第一个数是0,第二个数是1,后续每一项都是前两项的和。
- 数列的前几项为:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
填写代码:
class Fibonacci:
def __init__(self, n): ... # 填写此方法的代码
def __iter__(self):... # 填写此方法的代码
def __next__(self): ... # 填写此方法的代码
fibonacci_list = list(Fibonacci(20))
print('前20个斐波那契数列:', fibonacci_list)