深入了解可迭代的(iterable)、迭代器(iterator)、生成器(generator)最好的方法还是通过代码案例。
下面我们通过斐波那契数列类的案例来详细了解迭代器、生成器。
class Fib(object):
# count表示生成斐波那契数列的个数
def __init__(self, count):
self.count = count
# 保存前两个值
self.x = 0
self.y = 1
# 记录生成数列的下标
self.index = 0
# 声明Fib类是可迭代的
def __iter__(self):
return self
# 生成下一个数
def __next__(self):
if self.index < self.count:
result = self.x
self.x, self.y = self.y, self.x + self.y
self.index += 1
return result
else:
raise StopIteration
# 创建迭代器
fib = Fib(6)
# 获取迭代器下一个值
print(next(fib))
# 遍历迭代器其余的值
for value in fib:
print(value)
print(fib)
ll = (i for i in range(10))
print(ll)
out:
0
1
1
2
3
5
<__main__.Fib object at 0x000001E493DF5700>
<generator object <genexpr> at 0x000001E493936430>
迭代器(iterator)
迭代器指有__iter__方法的函数运行或类创建实例后生成的命名空间。打印迭代器显示的就是某某对象在内存某处,迭代器实质是一个内存地址,通过特定的方法访问该地址可以获得相应的数据。
紧接着前面的代码,测试下列代码。
fib1 = Fib(6)
fib2 = Fib(5)
print(fib1)
print(fib2)
out:
<__main__.Fib object at 0x000001AD3E445700>
<__main__.Fib object at 0x000001AD3E48A4F0>
可以看到fib1和fib2虽然内部代码相同,但由于它们的参数不同所以它们有不同的命名空间,那么它们就是不同的迭代器。
生成器(generator)
生成器指获取迭代器内部数据的方法或函数。注意方法和函数本身不是生成器,只有执行后有命名空间且可以返回值的才是生成器。
def even(n): # 定义一个返回值是偶数的生成器,值范围在0至n之间
i = 0
while i <= n:
if i % 2 == 0:
yield i
i += 1
print('__iter__' in dir(even))
print('__next__' in dir(even))
num = even(5)
print('__iter__' in dir(num))
print('__next__' in dir(num))
out:
False
False
True
True
生成器有2种:
- 通过__next__方法return返回值。例子是上面的Fib类。
- 通过yield或yield from语句返回值。例子是上面的even函数。有yield或yield from语句的函数在执行后会自动生成__iter__方法和__next__方法。
小结
今天通过案例详细了解了python的迭代器和生成器。一句话总结python的迭代器和生成器:
- python的迭代器实质是命名空间。
- python的生成器是访问迭代器获得数据的方法(或函数)。
预告
明天将详细梳理可迭代对象的getitem方法,后天是yield和yield from以及send。