1.背景
在python中,有很多对象都可以通过for循环来对其中的每一个元素进行访问,比如list、dict、string等,这些对象被称为可迭代对象。
2.什么是迭代器
迭代器(Iterator)是访问集合内元素的一种方式,提供了一种遍历序列对象的方法。用来迭代操作对象,可以像列表一样,迭代的获取其中的每一个元素,任何实现了__next__
方法的对象,都可以称之为迭代器。
3.迭代器的特点
__iter__()
方法返回迭代器本身
next()
方法返回容器的下一个元素
当没有下一个元素时,会报出StopIteration
异常
4.与列表的区别
构建迭代器的时候,不需要像列表一样,把所有的元素一次性加载到内存,而是通过使用延迟计算(lazy evaluation)的方式返回元素,这是迭代器的优点之一。
举例:如果一个列表包含一千万个整数,需要占用400M的内存,如果使用迭代器,只需要几十字节的内存。因为迭代器没有把所有元素加载到内存,而是调用迭代器的next()
方法时才返回该元素。
5.迭代器的例子
alist = [1,2,3,4,5,6,7,8,9]
it = iter(alist)
这里创建了一个列表,然后使用了iter()
方法实现了迭代器。
打印看一下是不是迭代器类型
print(it)
<list_iterator object at 0x000002903BE35278>
那么如何遍历迭代器里面的元素呢,下面是一些方法。
当我们使用next()
方法时,会按顺序返回迭代器中的元素,比如第一次调用next()
方法,返回列表中的元素1,第二次调用next()
方法,会返回列表中第二个元素2。
print(next(it))
print(next(it))
print(next(it))
1
2
3
那么如何遍历所有的元素呢,每一次都用next()
不太现实,这里就要用到循环,第一种方式while循环:
while True:
try:
print(next(it))
except StopIteration:
break
1
2
3
4
5
6
7
8
9
注意,这里用while True不断地取出迭代器中的元素,但是当超出范围时,会报出StopIteration异常,所以这里用Try-expect来捕获异常。
第二种方式:利用for循环
for item in it:
print(item)
1
2
3
4
5
6
7
8
9
直接利用for-in结构,取出迭代器中的每一个元素,然后输出,很明显比上面一种方法简洁很多。
如果需要在遍历的同时取出元素的索引值,只需要使用enumerate()
即可,和一般的列表之类的遍历相同:
for index,item in enumerate(it):
print(index,item)
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
接下来让我们自己编写一个迭代器的类,斐波那契数列
class Fib():
def __init__(self,n):
self.prev = 0
self.cur = 1
self.n = n
print(self.n)
def __iter__(self):
return self
def __next__(self):
if self.n > 0:
value = self.cur
self.cur = self.cur + self.prev
self.prev = value
self.n -= 1
return value
else:
raise StopIteration()
f = Fib(10)
for item in f:
print(item)
在20个迭代后停止
class myclass():
def __init__(self):
self.n = 1
def __iter__(self):
return self
def __next__(self):
if self.n <= 20:
# 必须新引入1个变量a,否则循环次数是20,但输出大小都会+1
a = self.n
self.n += 1
return a
else:
raise StopIteration()
myclass = myclass()
myiter = iter(myclass)
for item in myiter:
print(item)
简易的列表容器迭代器,支持迭代
class listDemo():
def __init__(self):
self.__date = []
self.__step = 0
def __next__(self):
if self.__step <= 0:
raise StopIteration
self.__step -= 1
# 返回下一个元素
return self.__date[self.__step]
def __iter__(self):
# 实例对象本身就是迭代器对象,因此直接返回self即可
return self
# 添加元素
def __setitem__(self,key,value):
self.__date.insert(key,value)
self.__step += 1
mylist = listDemo()
mylist[0] = 1
mylist[1] = 2
mylist[2] = 3
mylist[3] = 4
for i in mylist:
print(i)