对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是Python内置函数。
iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。
1,迭代器协议:对象需要提供next()方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
2,可迭代对象:实现了迭代器协议对象。list、tuple、dict都是Iterable(可迭代对象),但不是iteration(迭代器对象)。但可以使用内建函数iter(),把这些都变成iteration(迭代器对象)。
# 随便定义一个listlistArray=[1,2,3]# 使用iter()函数iterName=iter(listArray)print(iterName)# 结果如下:是一个列表list的迭代器# print(next(iterName))print(next(iterName))print(next(iterName))print(next(iterName))#没有迭代到下一个元素,直接抛出异常# 1# 2# 3# Traceback (most recent call last):# File "Test07.py", line 32, in # StopIteration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 计算出菲波那切数列classFib(object):def__init__(self, max):super(Fib, self).__init__() self.max = maxdef__iter__(self):self.a =0self.b =1returnselfdef__next__(self):fib = self.aiffib > self.max:raiseStopIteration self.a, self.b = self.b, self.a + self.breturnfib# 定义一个main函数,循环遍历每一个菲波那切数defmain():# 20以内的数fib = Fib(20)foriinfib: print(i)# 测试if__name__ =='__main__': main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
解释说明:
在本类的实现中,定义了一个iter(self)方法,这个方法是在for循环遍历时被iter()调用,返回一个迭代器。因为在遍历的时候,是直接调用的python内置函数iter(),由iter()通过调用iter(self)获得对象的迭代器。有了迭代器,就可以逐个遍历元素了。而逐个遍历的时候,也是使用内置的next()函数通过调用对象的next(self)方法对迭代器对象进行遍历。所以要实现iter(self)和next(self)。
而且因为实现了next(self),所以在实现iter(self)的时候,直接返回self就可以。
总结一句话就是:在循环遍历自定义容器对象时,会使用python内置函数iter()调用遍历对象的iter(self)获得一个迭代器,之后再循环对这个迭代器使用next()调用迭代器对象的next(self)。
注意点:iter(self)只会被调用一次,而next(self)会被调用 n 次,直到出现StopIteration异常。
>延迟操作。也就是在需要的时候才产生结果,不是立即产生结果。
>生成器是只能遍历一次的。
第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
如下案例加以说明:
# 菲波那切数列defFib(max):n, a, b =0,0,1whilen < max:yieldb a, b = b, a + b n = n +1return'亲!没有数据了...'# 调用方法,生成出10个数来f=Fib(10)# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中whileTrue:try: x=next(f) print("f:",x)exceptStopIterationase: print("生成器最后的返回值是:",e.value)break
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。
如下案例加以说明:
# 一个列表xiaoke=[2,3,4,5]# 生成器generator,类似于list,但是是把[]改为()gen=(aforainxiaoke)foriingen: print(i)#结果是:2345# 为什么要使用生成器?因为效率。# 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。# 如果你构造一个列表(list)的目的仅仅是传递给别的函数,# 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧!# 本案例是直接把列表转化为元组kk=tuple(aforainxiaoke)print(kk)#结果是:(2,3,4,5)# python内置的一些函数,可以识别这是生成器表达式result1=sum(aforainrange(3))print(result1)# 列表推导式result2=sum([aforainrange(3)])print(result2)