python iterator_python的迭代器为什么一定要实现__iter__方法?

这个问题,其实问的比较深了。

我分两部分来说清楚。第一部分,先把一些概念说清楚。见后面。我这里先说第二部分,回答正题。

====================

第二部分:

注:迭代器,为了和英文一致 我下面用 <迭代器对象 > 来取代。 另外<可迭代对象> 是容器一样的对象,要区别开。

一个象容器一样的对象,如果想要可以迭代,就需要实现 __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

====================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值