2022年 11月 3日

python迭代器(Iterator)

背景:

在python中,有很多对象都可以通过for循环来对其中的每一个元素进行访问,比如list、dict、string等,这些对象被称为可迭代对象

什么是迭代器

迭代器(Iterator)是访问集合内元素的一种方式,提供了一种遍历序列对象的方法。用来迭代操作对象,可以像列表一样,迭代的获取其中的每一个元素,任何实现了__next__方法的对象,都可以称之为迭代器。

迭代器的特点

__iter__方法返回迭代器本身;

next()方法返回容器的下一个元素

当没有下一个元素时,会报出StopIteration异常

与列表的区别

构建迭代器的时候,不需要像列表一样,把所有的元素一次性加载到内存,而是通过使用延迟计算(lazy evaluation)的方式返回元素,这是迭代器的优点之一。

举例:如果一个列表包含一千万个整数,需要占用400M的内存,如果使用迭代器,只需要几十字节的内存。因为迭代器没有把所有元素加载到内存,而是调用迭代器的next方法时才返回该元素。

迭代器的例子

  1. alist = [1,2,3,4]
  2. it = iter(alist)

这里创建了一个列表,然后使用了iter()方法实现了迭代器。

打印看一下是不是迭代器类型:

print(it)
<list_iterator object at 0x00000219B162C8E0>

那么如何遍历迭代器里面的元素呢,下面是一些方法。

当我们使用next()方法时,会按顺序返回迭代器中的元素,比如第一次调用next方法,返回列表中的元素1,第二次调用next方法,会返回列表中第二个元素2。

  1. print(next(it))
  2. print(next(it))
  1. 1
  2. 2

那么如何遍历所有的元素呢,每一次都用next不太现实,这里就要用到循环,第一种方式while循环:

  1. while True:
  2. try:
  3. print(next((it)))
  4. except StopIteration:
  5. break
  1. 1
  2. 2
  3. 3
  4. 4

注意,这里用while(True)不断的取出迭代器中的元素,但是当超出范围时,会报出StopIteration异常,所以这里用Try-expect来捕获异常。

第二种方式:利用for循环

  1. for item in it:
  2. print(item)

直接利用for-in结构,取出迭代器中的每一个元素,然后输出,很明显比上面一种方法简洁很多。

如果需要在遍历的同时取出元素的索引值,只需要使用enumerate即可,和一般的列表之类的遍历相同:

  1. for index,item in enumerate(it):
  2. print(index,item)

接下来让我们自己编写一个迭代器的类

  1. class Fib:
  2. def __init__(self,n):
  3. self.prev = 0
  4. self.cur = 1
  5. self.n = n
  6. print(self.n)
  7. def __iter__(self):
  8. return self
  9. def __next__(self):
  10. if self.n>0:
  11. value = self.cur
  12. self.cur = self.cur + self.prev
  13. self.prev = value
  14. self.n-=1
  15. return value
  16. else:
  17. raise StopIteration()
  18. f = Fib(10)
  19. for item in f:
  20. print(item)