这个问题,其实问的比较深了。
我分两部分来说清楚。第一部分,先把一些概念说清楚。见后面。我这里先说第二部分,回答正题。
====================
第二部分:
注:迭代器,为了和英文一致 我下面用 <迭代器对象 > 来取代。 另外<可迭代对象> 是容器一样的对象,要区别开。
一个象容器一样的对象,如果想要可以迭代,就需要实现 __iter__()这个方法。用这个方法,来返回一个 迭代器对象,这样的话,就可以被for in这样的语句来处理,象处理序列一样来处理。
那么定义中的 迭代器对象 要实现两个方法 __iter__()和next() (在python3中改成了 __next__()了)方法。
题主的问题是:迭代器对象 的本职工作是来做 next 的,为什么还要实现 __iter__(),返回它自己呢?
从语义上来说,是只需实现__next__()方法即可。但是, 迭代器对象实现了_iter__(),并返回它自己,就可以把它自己变成可迭代对象,那么 迭代器对象 就可以 象 可迭代对象 一样,用for in这种方法来 处理了。
例如:
m = iter(obj)
for n in m:
#do something.
这里的 m 就是由obj返回的一个迭代器对象,它由于实现了 _iter__() :return self , 所以变成了和obj一样的 可迭代对象,于是可以用for in来操作了。
在python官方文档 PEP 234 -- Iterators 中,有提到
Classes can define how they are iterated over by defining an __iter__() method; this should take no additional arguments and return a valid iterator object. A class that wants to be an iterator should implement two methods: a next() method that behaves as described above, and an __iter__()method that returns self.
The two methods correspond to two distinct protocols:An object can be iterated over with for if it implements __iter__() or __getitem__().
An object can function as an iterator if it implements next().
Container-like objects usually support protocol 1. Iterators are currently required to support both protocols. The semantics of iteration come only from protocol 2; protocol 1 is present to make iterators behave like sequences; in particular so that code receiving an iterator can use a for-loop over the iterator.
第一部分:
====================
分清了下面几个概念,也就搞懂了python的迭代器:
1、 可迭代类(class collections.abc.Iterable)
提供 __iter__() 这个方法的类,都是可迭代类,
或者 提供__getitem __() 这个方法的类,也是可迭代类
2、迭代器类(class collections.abc.Iterator)
同时提供 __iter__() 和 __next__() 这两个方法的类。
(从定义可以看出,迭代器类,一定是 可迭代类,因为它实现了__iter__()方法)
(从定义来看,迭代器类,要比可迭代类 多实现一个 __next()__方法。)
以上两个,在这个页面中可以找到:8.4. collections.abc - Abstract Base Classes for Containers - Python 3.6.3 documentation
以下两个,在这个页面中可以找到:
Glossary - Python 3.6.3 documentation
3、可迭代对象
简单来说,就是那些 list, str, 和tuple 用这些定义的对象,都是 可迭代对象,因为他们都实现了__iter__() 或 __getitem__()方法。(当然,也可以是你自己定义一个类 生成的一个对象,下面例子中:用Fib()类所生成的对象)
4、迭代器对象
代表 数据流的对象。传说中的迭代器。
你可以把 可迭代对象,当成一个容器(其实它就是一个容器 英文官方叫collections)。那么,如果你要从这个容器中,一个一个把里面的数据取出来,那么你可以 造作一个 迭代器类(例子中有kkk()),用它生成的迭代器对象(例子中的“K”,可以返回给iter()调用者 ),可以帮你一个一个从容器里取数据。所以,迭代器必须实现—__next__()方法。(注意python3以后,只能叫__next__()方法,这个方法不能带参数)
因为 迭代器类 也实现了__iter__()方法,所以它当然也是一个 可迭代类。
迭代器对象是如何得到的呢,很简单, d = iter(kkk) 就可以把 kkk 的迭代器对象(“K”)取出来了。
(注意:1、 这里的iter()函数,不同于__iter__();2、kkk 必须是一个可迭代对象,比如是 kkk = [1,3,5,4,3,100]这样的,或是kkk内实现了 __iter__()方法。)
一般来说,当你自己定义一个可迭代类时,我们希望用 一个 迭代器对象 来取 它自己的数据,所以__iter__()只需要返回自己即可,即return self。
总结一下: 分清两个类,两个对象。 一个对话:
##### 主程序说:
既然你是一个可迭代对象,那请把 你的迭代器(迭代器对象),给我玩一玩啊。
##### 可迭代对象:
好啊,你来拿吧。
##### 主程序说:
怎么拿啊?
##### 可迭代对象:
你 iter()一下我啊!
##### 主程序说:
OK,拿到。
##### 主程序说:
好好玩啊,你的这个迭代器,晃一下,出来一个东西,晃一下又出来一个。
##### 可迭代对象:
那是当然,不过,我的这个迭代器,不能老晃,不然晃完了,可就没有了哦。隔壁老王家也有一个迭代器,它那个随便你,想晃多少晃多少。
对话结束。
最后,大家网络上所说的迭代器, 一般是指 迭代器对象, 即英文材料中所指的 iterator。
```
$ cat fib.py
from collections import Iterable
class kkk(object):
def __init__(self):
self.a = 1
def __iter__(self):
return self
def __next__(self):
self.a = self.a + 1
if self.a > 20: # 退出循环的条件
raise StopIteration();
return self.a
def next(self):
return self.a + 1000
class Fib(object):
#class Fib(Iterable):
def __init__(self,m,n):
self.a, self.b = 0, 1 # 初始化两个计数器a,b
self.m = m
self.n = n
self.K = kkk() #kkk也是一个可迭代类,同时,也是一个迭代器类
#根据需要,你可以返回不同的迭代器对象。
def __iter__(self):
if self.m ==5:
return self.K
else:
return self
#return self # 实例本身就是迭代对象,故返回自己
def next(self): # next()在python3中,已经不具有其它含义,只是普通的一个方法。
return self.a + 5555
def addd(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值
def __next__(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值
if __name__ == '__main__':
x = Fib(5,6)
print(x.__next__())
print(x.__next__())
print(x.__next__())
print(x.__next__())
print(x.next())
print(x.next())
print(x.next())
print(x.next())
print( "---------------------------------")
print(x.addd())
print(x.addd())
print(x.addd())
print(x.addd())
print( "------in Fib(5,4)---------------------------")
for n in Fib(5,4):
print (n)
print( "------in Fib(3,4)---------------------------")
for n in Fib(3,4):
print (n)
print( "-------------in m --5,4------------------")
m = Fib(5,4)
for n in m:
print(n)
print( "-------------in m --3,4------------------")
m = Fib(4,4)
"""
print("-----m.next() is:",m.next() )
print("-----m.next() is:",m.next() )
print("-----m.next() is:",m.next() )
"""
for n in m:
print(n)
print( "-------------in iter(m) --5,4------------------")
m = Fib(5,4)
x = iter(m) #请问,iter是谁的内置函数
print("-----iter(m).next() is:",x.next() )
print("-----iter(m).next() is:",x.next() )
print("-----iter(m).next() is:",x.next() )
for n in x:
print(n)
print( "-------------in iter(m) --3,4------------------")
m = Fib(3,4)
x = iter(m)
print("-----iter(m).next() is:",x.next() )
print("-----iter(m).next() is:",x.next() )
print("-----iter(m).next() is:",x.next() )
print("-----iter(m).next() is:",x.__next__() )
print("-----iter(m).next() is:",x.__next__() )
print("-----iter(m).next() is:",x.__next__() )
print("-----iter(m).next() is:",x.__next__() )
print("-----iter(m).next() is:",x.__next__() )
for n in x:
print(n)
print( "-----------------in iter(m) again---------------")
y = iter(m)
for n in y:
print(n)
print( "--------------end-------------------")
#Fib.__next__()
L = [1,3,2,5,6,7,9,6]
for n in iter(L):
print("L:",n)
for n in iter(L):
print("L:",n)
print(dir("__builtins__"))
print(dir("__class__"))
$
```
运行结果:
```
$ python fib.py
1
1
2
3
5558
5558
5558
5558
---------------------------------
5
8
13
21
------in Fib(5,4)---------------------------
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
------in Fib(3,4)---------------------------
1
1
2
3
5
8
13
21
34
55
89
-------------in m --5,4------------------
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-------------in m --3,4------------------
1
1
2
3
5
8
13
21
34
55
89
-------------in iter(m) --5,4------------------
-----iter(m).next() is: 1001
-----iter(m).next() is: 1001
-----iter(m).next() is: 1001
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-------------in iter(m) --3,4------------------
-----iter(m).next() is: 5555
-----iter(m).next() is: 5555
-----iter(m).next() is: 5555
-----iter(m).next() is: 1
-----iter(m).next() is: 1
-----iter(m).next() is: 2
-----iter(m).next() is: 3
-----iter(m).next() is: 5
8
13
21
34
55
89
-----------------in iter(m) again---------------
--------------end-------------------
L: 1
L: 3
L: 2
L: 5
L: 6
L: 7
L: 9
L: 6
L: 1
L: 3
L: 2
L: 5
L: 6
L: 7
L: 9
L: 6
====================