一·迭代器
可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
所有的Iterable均可以通过内置函数iter()来转变为Iterator。
对迭代器来讲,有一个__next__()就够了。在你使用for 和 in 语句时,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的__next__()方法,直到监测到一个StopIteration异常。
相关BIF: iter() next()
一下为IDLE环境下的演示
>>> string = 'tecent'
>>> it = iter(string)
>>> next(it)
't'
>>> next(it)
'e'
>>> next(it)
'c'
>>> next(it)
'e'
>>> next(it)
'n'
>>> next(it)
't'
>>> next(it)
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
next(it)
StopIteration
>>>
下面是for迭代的工作原理
string = 'tencent'
it = iter(string)
while True:
try:
each = next(it)
print(each)
except StopIteration:
break
输出结果
t
e
n
c
e
n
t
>>>
对应魔法方法:__iter__() __next__()
我们以斐波那契数列进行演示
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def __iter__(self):
return self
def __next__(self):
self.a,self.b = self.b,self.a+self.b
return self.a
fibs = Fibs()
for each in fibs:
if each<100:
print(each)
以下是输出结果
1
1
2
3
5
8
13
21
34
55
89
二·.生成器
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。
生成器的特点:
生成器是一个函数,而且函数的参数都会保留。
迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
yield 生成器的运行机制:
当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把yield 的参数给你,之后生成器就不会往下继续运行。 当你问他要下一个数时,他会从上次的状态。开始运行,直至出现yield语句,把参数给你,之后停下。如此反复
直至退出函数。(以上关于yield的描述,在后面列举一个简单的例子来解释这段话)
yield的使用:
在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器,它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数,如:
>>> c = h() #h()包含了yield关键字
>>> #返回值
>>> c.next()
每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。
下面,来看看以下的例子代码吧,是用来说明yield运行机制的。
def fib(max):
a, b = 1, 1
while a < max:
yield a
a, b = b, a+b
#程序运行:
for n in fib(15):
print(n)