python迭代器&for循环原理
本节主要学习内容有两点:python迭代器;for循环原理。
在介绍这两点前我们要了解什么是可迭代对象,下面依次介绍之。
可迭代对象
可迭代对象(iterable)指的是可以依次返回其内部成员的对象。比如字符串、列表、字典、文件等都是可迭代对象。从语法方面说就是那些具有__iter__
的方法的对象,对于类来说指的是那些具有__getitem__
方法的对象。
迭代器
python一切皆对象,迭代器(iterator)也可以说是迭代器对象。具有__iter__
方法的对象调用__iter__
会返回一个迭代器对象。从语法上说就是那些同时具有__next__
和__iter__
方法的对象。
- 迭代器调用
__next__
方法会调用迭代器中的下一个值; - 迭代器调用
__iter__
方法返回迭代器本身;
# 迭代器对象表示一种数据流,会通过重复调用其__next__方法(同将其传参给内置函数next)从数据流中返回一个元素;
# 当数据流中没有数据元素时,就会抛出一个 StopIterationd的异常。
# 迭代器也有一个__iter__方法,也就是说迭代器也是一个可迭代对象,我们又知道迭代器调用其__iter__方法返回的是其迭代器本身;
# 这看起来是似乎是多余鸡肋的,但如果从全局上看这样做的好处是巨大了,它能够让迭代器使用的更灵活(在可迭代器的位置上也可以使用迭代器)
>>> s={1,2,3} # 可迭代对象s
>>> i=iter(s) # 本质就是在调用s.__iter__(),返回s的迭代器对象i,
>>> next(i) # 本质就是在调用i.__next__()
1
>>> next(i)
2
>>> next(i)
3
>>> next(i) #抛出StopIteration的异常,代表无值可取,迭代结束
python文件是一个可迭代对象,同时也是一个迭代器。
迭代器是Python提供的一种统一的、不依赖于索引的迭代取值方式,只要存在多个"值",无论序列类型还是非序列类型都可以按照迭代器的方式取值。
迭代器优缺点
优点:
- 为序列和非序列类型提供了一种统一的迭代取值方式;
- 惰性取值;每次只取一个数据,不占内存;迭代器保存的是产生数据的算法,而不是实际的数据。
缺点:
- 除非取尽,否则无法获取迭代器的长度;
- 只能往后依次取值,不能返回头往前取值。就像象棋中的卒,只进不退。
for循环原理
while循环是条件循环;for循环是迭代器循环;
刚开始接触python流程控制的循环结构时,我们知道while循环可以实现for循环的所有功能,之所以使用for循环主要是使用其方便又强大的遍历取值功能。for循环的这种遍历取值功能本质上是利用了迭代器的原理。
# while + iterator
goods=['mac','lenovo','acer','dell','sony']
goods_iterator = iter(goods) # 等同于goods.__iter__()
while True:
try:
print(next(goods_iterator)) # 等同于goods.__next__()
except StopIteration: # 捕捉异常终止循环
break
# for循环
for i in goods:
print(i)
为什么for循环会如此简洁?这是因为for循环底层我们做了:
- 第一,调用可迭代对象的
__iter__
方法,将goods转化为迭代器goods_iterator; - 第二,调用迭代器goods_iterator的
__next__
方法,返回出goods的第一个元素; - 第三,循环步骤2,直到迭代器内数据流全部输出,捕获异常()