[python 笔记] __iter__迭代器

可迭代对象和迭代器

https://blog.csdn.net/nightcharm/article/details/78964676

可迭代对象

对象里面含有__iter__()方法的实现,对象的__iter__()函数经调用后会返回一个迭代器,这个迭代器含有具体数据获取的实现。

迭代器

包含__next__()方法的实现,在正确范围内返回下一个可用元素;超出范围后抛出StopIteration,通知调用者迭代结束。

迭代器工作的基本步骤

https://blog.csdn.net/bluebird_237/article/details/38894617

1. 可迭代对象调用 __iter__()方法返回迭代器(self)

2. 迭代器调用__next()__ 函数,返回下一个可用元素;如果没有元素了,抛出StopIteration

for... in...的实现原理

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

我们以斐波那契数列为例,写一个Fib类,可以作用于for循环

 1 class Fib(object):
 2     def __init__(self):
 3         self.a, self.b = 0, 1
 4 
 5     def __iter__(self):
 6         return self
 7 
 8     def __next__(self):
 9         self.a, self.b = self.b, self.a + self.b
10         if self.a > 1000:
11             raise StopIteration();
12         return self.a
13 
14 for n in Fib():
15     print(n)
16 
17 
18 # 1
19 # 2
20 # 3
21 # 5
22 # 8
23 # 13
24 # 21
25 # 34
26 # 55
27 # 89
28 # 144
29 # 233
30 # 377
31 # 610
32 # 987

注意:在python 3中应使用__next__(), 而非 next(), 否则会报错:TypeError: iter() returned non-iterator of type 'Fib'。

实现的大致流程:

 1 for i in seq:
 2     do_sth_to(i)
 3 
 4 ################
 5 
 6 fetch = iter(seq) #return an iterator
 7 while True:
 8     try:
 9         i = fetch.next() # iterator call __next__()
10     except StopIteration: 
11         break    # iteration finished
12     do_sth_to(i)

迭代器的工作原理

迭代器相当于一个有__next__()方法的对象,当(一个循环机制)需要下一项时,调用迭代器的__next__()方法即可获得。条目全部被取出后,会引发一个StopIteration异常,通知外部调用者,迭代完成。

迭代器的限制

1. 不能向后移动回到开始

2. 不能复制一个迭代器

3. 若要再次(或同时)迭代同个对象,只能去创建另一个迭代器对象

4. 迭代时请尽量不要修改该对象,否则可能会出错

其他工具:

1. reversed()内建函数将返回一个反序访问的迭代器

2. enumerate()内建函数返回迭代器

3. any(), all()

4. python提供itertools 模块, 它包含各种有用的迭代器

对比生成器

迭代器是一个对象,生成器是一个函数。

迭代器和生成器是python中两个非常强大的特性,编写程序时你可以不使用生成器达到同样的效果,但是生成器让你的程序更加pythonic。

创建生成器非常简单,只要在函数中加入yield语句即可。函数中每次使用yield产生一个值,函数就返回该值,然后停止执行,等待被激活,被激活后继续在原来的位置执行。

 1 def fib():
 2     a, b = 0, 1
 3     while 1:
 4         a, b = b, a + b
 5         yield a
 6 
 7 for f in fib():
 8     if f < 1000:
 9         print(f)
10     else:
11         break