迭代器
迭代是什么
我们知道可以对list,tuple,dict,str等数据类型使用for...in...的循环语法,从中依次取出数据,这个过程叫做遍历,也称迭代(迭代是访问集合元素的一种常用方式)
可迭代对象是什么
可以用for...in...循环语句从中取出数据的对象,就是可迭代对象,例如:列表、元组、字典、字符串都是可迭代对象;而整数、浮点数、布尔值均是不可迭代对象
迭代器是什么
每迭代一次即在for...in...中每循环一次,都会返回对象中的下一条数据,一直向后读取数据直到迭代了所有数据之后结束,而在这个过程中应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据,外面把这个每次能帮我们进行数据迭代的“人”,称之为迭代器(Iterator)
例如:老师安排学生每节课上课前进行演讲,按照学号顺序进行,A同学这节课演讲,老师会记住A同学演讲过了,那么下节课就是B同学进行演讲了....以此类推,在这里,老师就充当了“迭代器”的角色了。
如何获取可迭代对象的迭代器
我们可以通过iter()内置函数取得可迭代对象的迭代器
list=[1,2,3,4] #list是可迭代对象
it=iter(list) #创建迭代器对象:通过lter()方法取得list的迭代器
print(it)
结果:
<list_iterator object at 0x000002235A16A460>
利用next()函数通过迭代器获取下一个位置的值
注意:当我们迭代完最后一个数据之后,再次调用next()函数时会抛出StopIteration的异常,来告诉我们所有数据都已迭代完成,不用再执行next()函数了
list=[1,2,3,4] #list是可迭代对象
it=iter(list) #创建迭代器对象:通过lter()方法取得list的迭代器
print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))
结果:
1
2
3
4
Traceback (most recent call last):
File "D:\Python_test\day1\xx.py", line 7, in <module>
print(next(it))
StopIteration
判断一个对象是否可迭代
isinstance(object,classinfo)内置函数可以判断一个对象是否是一个已知的类型,类似 type()。
- object -- 实例对象。
- classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。
collections模块里的Iterable,凡是可迭代对象都是这个类的实例对象。
import collections
print(isinstance([1,2,3],collections.Iterable))
print(isinstance((1,2,3),collections.Iterable))
print(isinstance({"name":"chichung","age":23},collections.Iterable))
print(isinstance("sex",collections.Iterable))
print(isinstance(123,collections.Iterable))
print(isinstance(True,collections.Iterable))
print(isinstance(1.23,collections.Iterable))
结果:
True
True
True
True
False
False
False
可迭代对象如何获取迭代器
迭代对象是由collections模块里的Iterable类创建出来的实例的,你写一个列表,它是Iterable类创建的实例对象
class Iterable(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def __iter__(self): # 注意__iter__(self)方法
while False:
yield None
由Iterable创建的对象,是有一个方法_iter_(self)的,此方法返回一个迭代器,所以,由Iterable类创建的实例对象,是可以拿出一个迭代器的。
之所以Iterable类创建的对象是可迭代对象,是因为Iterable类有这个方法(_iter_(self))!
import collections
class BecomeIterable:
def __iter__(self):
"""返回一个空的迭代器"""
return None
people = BecomeIterable()
print(isinstance(people, collections.Iterable))
结果:
True
迭代器为何能用next()函数进行迭代呢
我们知道使用iter()函数,在可迭代对象中获取迭代器,Iterator=iter([1,2,3,4]),使用next(),是因为iter()函数能调用可迭代对象的方法__iter__(),从而返回一个迭代器。如何返回?__iter__()方法是使用collections模块里的Iterator类来创建一个迭代器对象。
class Iterator(Iterable):
__slots__ = ()
@abstractmethod
def __next__(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
raise StopIteration
def __iter__(self):
return self
如果超出迭代方位就抛出StopIteration异常
创建一个迭代器类
class MyIterator():
def __init__(self):
self.list = []
self.position = 0
def add_name(self,name):
self.list.append(name)
def __iter__(self):
return self # 返回一个迭代器
def __next__(self):
if self.position < len(self.list):
item = self.list[self.position]
self.position += 1
return item
else:
raise StopIteration
people = MyIterator() # people对象既是一个迭代器,也是一个可迭代对象
people.add_name("张三")
people.add_name("李四")
people.add_name("王五")
# 把people当做一个迭代器来看时
print(next(people))
print(next(people))
print(next(people))
# 把humen当做一个可迭代对象来看时
humen = MyIterator() # 因为迭代器只能用一次,再用会抛出错误,所以需要再创建
humen.add_name("张三")
humen.add_name("李四")
humen.add_name("王五")
iterator = iter(humen) # iter()方法获取可迭代对象的迭代器
print(next(iterator))
print(next(iterator))
print(next(iterator))
结果:
张三
李四
王五
张三
李四
王五
生成器
yieId的函数被称为生成器(generator)
与普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作(生成器就是迭代器)
在调用生成器运行的过程中,每次遇到yieId时函数会暂停并保存当前所有的运行信息,返回yieId的值,并在下一次执行next()方法时,从当前位置继续运行(调用一个生成器函数,返回一个迭代器对象)
使用斐波那契数列写一个实例
import sys
def fibonacci(n): #生成器函数-斐波那契
a,b,counter =0,1,0
while True:
if (counter > n):
return
yield a
a,b,=b,a+b
counter += 1
f=fibonacci(10) #f是一个迭代器,由生成器返回生成
while True:
try:
print(next(f),end=" ")
except StopIteration:
sys.exit()
结果:
0 1 1 2 3 5 8 13 21 34 55