简介
在Python中存在一种名叫迭代器的容器对象。顾名思义,这种对象能够产生迭代的数值,在许多场合中,比如在机器学习领域,要从一个迭代器里不断地提取样本数据进行训练。而生成器也是一种迭代器,因此在本文中将详细介绍迭代器的知识。
迭代器定义
迭代器也称为游标,形象地理解为程序运行到哪里就在该处做个标记,下次程序从该处继续执行。通过迭代器的方法可以将迭代器中的元素一一提取出来,那么迭代器本身是什么呢?这就要先讲到可迭代对象了。
可迭代对象
可迭代对象并不是迭代器,但是可以通过iter()函数将可迭代对象转换成迭代器。一般来说,可以使用for循环遍历的对象称为可迭代对象,那我们自然就能想到一些常见的可迭代对象了:
列表;
元组;
字符串;
字典;
文件。
我们可以将以上可迭代对象转换成迭代器,而迭代器本身就是一个迭代器对象。
>>>a = iter('finthon')
>>>a
1
2
3
>>>a=iter('finthon')
>>>a
迭代器方法
这里主要介绍读取迭代器元素的方法,一般通过next()函数或者__next__()方法实现。
例如我们想读取上面构建的迭代器a,可以这样操作:
>>>next(a)
'f'
>>>next(a)
'i'
#或者使用__next__()方法
>>>a.__next__()
'n'
>>>a.__next__()
't'
>>>a.__next__()
'h'
>>>a.__next__()
'o'
>>>a.__next__()
'n'
>>>a.__next__()
Traceback (most recent call last):
File "", line 1, in
a.__next__()
StopIteration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>>next(a)
'f'
>>>next(a)
'i'
#或者使用__next__()方法
>>>a.__next__()
'n'
>>>a.__next__()
't'
>>>a.__next__()
'h'
>>>a.__next__()
'o'
>>>a.__next__()
'n'
>>>a.__next__()
Traceback(mostrecentcalllast):
File"",line1,in
a.__next__()
StopIteration
依次从迭代器a中取出了其中的元素,当迭代器取完元素后就空了,此时再想取出元素就会引发停止迭代的异常StopIteration。
生成器定义
生成器也是一种迭代器,因此next()函数和__next__()方法也可以在生成器中使用。有两种方法构建生成器:
通过yield关键字实现;
通过生成器表达式实现。
yield关键字在函数中使用,返回函数的值并在此做好标记,下次从标记处继续调用该函数,返回函数的值。首先来看个例子:
def finthon():
yield 2
yield 5
yield 'hello'
1
2
3
4
deffinthon():
yield2
yield5
yield'hello'
在上面的程序中我们定义了一个finthon()函数(函数在下一章会讲到),该函数代码块中有三句包含yield关键字的语句,我们可以执行该函数:
>>>x = finthon()
>>>x
1
2
3
>>>x=finthon()
>>>x
通过将函数赋值给变量x,创建了一个生成器x,接下来我们调用这个生成器:
>>>next(x)
2
>>>next(x)
5
>>>next(x)
'hello'
1
2
3
4
5
6
>>>next(x)
2
>>>next(x)
5
>>>next(x)
'hello'
可以看出yield语句的作用是返回对应的值给函数,标记此处并暂时把该函数挂起,当使用next()函数时,将继续执行标记处后面的语句。
生成器表达式
这是另一种构建生成器的方法,通过以下格式:
生成器名 = (i for i in xxx)
1
生成器名=(iforiinxxx)
其中xxx是一个可迭代对象,注意用()包含,语句的意思是先对xxx进行for循环,每次取出i后进行i的运算,这里直接返回i,举个例子:
>>>a = (i * 2 for i in range(3))
>>>a
at 0x000001D7DB5FE468>
1
2
3
>>>a=(i*2foriinrange(3))
>>>a
at0x000001D7DB5FE468>
可以看出此时构建了一个生成器a,它是一个包含i * 2的值,我们可以继续调用其中的元素:
>>>next(a)
0
>>>next(a)
2
>>>next(a)
4
1
2
3
4
5
6
>>>next(a)
0
>>>next(a)
2
>>>next(a)
4
需要特别强调的是这种格式与列表解析非常类似,列表解析返回的是一个列表,格式如下:
列表名 = [i for i in xxx]
1
列表名=[iforiinxxx]
这种格式与生成器唯一的不同就是使用[],一定不能使用错了:
>>>a = [i * 2 for i in range(3)]
>>>a
[0, 2, 4]
1
2
3
>>>a=[i*2foriinrange(3)]
>>>a
[0,2,4]
可见返回的a是一个列表,如果要变成迭代器就要使用iter()函数转换一下。
总结
我们在这里具体介绍了迭代器以及迭代器中的生成器,通过next()函数或__next__()方法调用内部元素,通过iter()函数能够将可迭代对象转换成迭代器。最后可以使用yield关键字和生成器表达式两种方法构建生成器。学习完本文,以后我们就可以构建一些自定义的迭代器完成指定任务了。