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