生成器(Generator)
下例中generator_tri的名称叫做生成器(Generator),是一种特殊的 Iterator对象,注意生成器一定是迭代器,迭代器不一定是生成器, 生成器获取方式:
a.Generator函数返回
b.生成器表达式
Generator函数返回,以杨辉三角为例:
from collections import Iterator
from collections import Iterable
from typing import Generator
def triangle():
result = [1]
while True:
yield result
result = [([0] + result)[i]+(result + [0])[i] for i in range(len(result) + 1)]
generator_tri = triangle()
generator_tri.__next__()
print(next(generator_tri))
print("generator_tri is " + ("Iterator" if isinstance(generator_tri, Iterator) else "not Iterator"))
print("generator_tri is " + ("Iterator" if isinstance(generator_tri, Iterable) else "not Iterable"))
print("generator_tri is " + ("Generator" if isinstance(generator_tri, Generator) else "not Generator"))
print("generator_tri's type is ", type(generator_tri))
生成器表达式:
IL = (x for x in range(10))
print("IL's type is ", type(IL))
运行结果为:
[1, 1]
generator_tri is Iterator
generator_tri is Iterator
generator_tri is Generator
generator_tri's type is <class 'generator'>
IL's type is <class 'generator'>
Generator函数
上例中triangle()函数叫做Generator函数,即可以返回生成器(Generator)的函数
迭代器(Iterator)
Iterator对象 必须包含__iter__()函数,__next()__函数(接口), 分别供全局函数 iter()(此函数的功能就是返回一个Iterator对象)和next()调用, Iterator中的__iter__()函数只需要返回它自身即可Iterator对象的获取方式有:
a.生成器(生成器的获取方式见上)
b.Iterable对象(容器类等) 通过iter()函数转换
可迭代对象(Iterable)
list,dict, set 等容器类都是可迭代对象(Iterable),即作为iter()函数的参数,调用后,可返回迭代器的对象,Iterable必须包含__iter__()函数,供全局函数iter()调用, 并返回一个迭代器(Iterator)
L = [x for x in range(10)]
L = iter(L)
print("L's type is ", type(L))
print("s is " + ("Iterable" if isinstance(L, Iterable) else "not Iterable"))
运行结果:
L's type is <class 'list_iterator'>
s is Iterable
for in 结构的本质
迭代器(Iterator)和可迭代对象(Iterable)都可以作为iter()函数的参数,都返回一个迭代器(Iterator)(对于Iterator做参数,返回的就是它自身 ),for ...in ...结构的本质就是调用iter()函数,根据返回的Iterator,然后调用next()函数 进行遍历。
示例1:
for x in [1, 2, 3, 4, 5]:
pass
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
#it = iter(iter([1, 2, 3,,4, 5]))#多次调用iter()函数时允许的,因为迭代器(Iterator)返回的是自身
# 循环:
#以上代码等价于
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break
示例2:
i = 0
for x in generator_tri:
i += 1
if i >5:
break
print(x)
#以上代码等价于
it = iter(generator_tri)#it 和generator_tri是一样的
i = 0
while i < 5:
i += 1
x = next(it)
print(x)
自定义迭代器Iterator
我们可以自定义一个类,包含__iter__() __next()函数,根据鸭子类型,冒充迭代器(Iterator),调用isinstance()判断是否是Iterator,返回trueclass Fib(object):
def __init__(self, max_lim):
self.a, self.b = 0, 1
if max_lim >= 0:
self.__max_lim = max_lim
else:
self.__max_lim = 0
def __iter__(self):
'供iter()调用,返回迭代器'
return self
def __next__(self):
'供next()函数调用'
self.a, self.b = self.b, self.a + self.b
if self.a > self.__max_lim:
raise StopIteration()
return self.a
f = Fib(1000)
print("f is " + ("Iterator" if isinstance(f, Iterator) else "not Iterator"))
print("f is " + ("Iterable" if isinstance(f, Iterable) else "not Iterable"))
print("f is " + ("Generator" if isinstance(f, Generator) else "not Generator"))
print(type(f))
print(next(f))
运行结果为:
f is Iterator
f is Iterable
f is not Generator
<class '__main__.Fib'>
1
小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
参考: