美文网首页Python七号
python 基础系列--可迭代对象、迭代器与生成器

python 基础系列--可迭代对象、迭代器与生成器

作者: somenzz | 来源:发表于2018-10-10 21:30 被阅读45次

迭代器是 Python 最强大的功能之一,可以想像如果有个几十 GB 的大文件,你需要编写程序处理其中的文本信息,如果一次性全部读入内存,估计机器会直接罢工了,但是借住可迭代对象,可以一次从硬盘读取一小块内容到内存,处理完后写回硬盘,不断迭代,从而节省内存,加快处理速度。

首先来解释这3个概念。
(1)可迭代对象:如果一个对象定拥有 __iter__ 方法,那么这个对象就是一个可迭代对象。这里顺便说下
for 循环的处理过程:在 Python 中我们经常使用 for 循环来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象,常见的有列表,元组,字典。for 循环开始时自动调用可迭代对象的 __iter__ 方法获取一个迭代器,for 循环时自动调用迭代器的 next 方法获取下一个元素,当调用可迭代器对象的 next 方法引发 StopIteration 异常时,结束 for 循环。

(2)迭代器:如果一个对象定拥有 __iter__ 方法和 __next__ 方法,那么这个对象就是一个迭代器。

(3)生成器:生成器是一类特殊的迭代器,就是在需要的时候才产生结果,不是立即产生结果。这样可以同时节省 CPU 和内存。有两类方法实现生成器:

  • 生成器函数。使用 def 定义函数,使用 yield 而不是 return 语句返回结果。yield 语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

  • 生成器表达式。类似于列表推导,只不过是把一对大括号 [] 变换为一对小括号() 。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。

三者之间的关系如下图所示。

三者之间的关系

可迭代对象包含迭代器、序列、字典;生成器是一种特殊的迭代器。下面分别举例说明。

创建一个迭代器

1  class MyListIterator(object):  # 定义迭代器类,其是MyList可迭代对象的迭代器类
2      
3      def __init__(self, data):
4          self.data = data  # 上边界
5          self.now = 0  # 当前迭代值,初始为0
6  
7      def __iter__(self):
8          return self  # 返回该对象的迭代器类的实例;因为自己就是迭代器,所以返回self
9  
10      def __next__(self):  # 迭代器类必须实现的方法
11          while self.now < self.data:
12              self.now += 1
13              return self.now - 1  # 返回当前迭代值  
14          raise StopIteration  # 超出上边界,抛出异常

类 MyListIterator 实现了 __iter__ 方法和 __next__ 方法,因此它是一个迭代器对象,由于 __iter__ 方法本返的是迭代器(本身),因此它也是可迭代对象。迭代器必然是一个可迭代对象。

下面使用3种方法遍历迭代器 MyListIterator。

1  my_list = MyListIterator(5)  # 得到一个迭代器
2  print("使用for循环来遍历迭代器")
3  for i in my_list:
4      print(i)
5  my_list = MyListIterator(5)  # 重新得到一个可迭代对象
6  print("使用next来遍历迭代器")
7  print(next(my_list))
8  print(next(my_list))
9  print(next(my_list))
10  print(next(my_list))
11  print(next(my_list))
12  my_list = MyListIterator(5)  # 重新得到一个可迭代对象
13  print("同时使用next和for来遍历迭代器")
14  print("先使用两次next")
15  print(next(my_list))
16  print(next(my_list))
17  print("再使用for,会从第三个元素2开始输出")
18  for i in my_list:
19      print(i)

输出结果如下:

使用for循环来遍历迭代器
0
1
2
3
4
使用next来遍历迭代器
0
1
2
3
4
同时使用next和for来遍历迭代器
先使用两次next
0
1
再使用for,会从第三个元素2开始输出
2
3
4

从结果可以看出,for 循环实际上就是调用了迭代器的 __next__方法,当捕捉到 MyListIterator 异常时自动结束 for 循环

创建一个可迭代对象

1  class MyList(object):  # 定义可迭代对象类
2      def __init__(self, num):
3          self.data = num  # 上边界
4      def __iter__(self):
5          return MyListIterator(self.data)  # 返回该可迭代对象的迭代器类的实例

上例中对象 MyList 实现了 __iter__ 方法返回了迭代器类的实例,因此它是一个可迭代对象。遍历操作可使用 for 循环,无法使用 next()。for 循环实质上还是调用 MyListIterator 的 __next__ 方法。

1  my_list = MyList(5)  # 得到一个可迭代对象
2  print("使用for循环来遍历可迭代对象my_list")
3  for i in my_list:
4      print(i)
5  my_list = MyList(5)  # 得到一个可迭代对象
6  print("使用next来遍历可迭代对象my_list")
7  print(next(my_list))
8  print(next(my_list))
9  print(next(my_list))
10  print(next(my_list))
11  print(next(my_list))

输出结果如下:

使用for循环来遍历可迭代对象my_list
0
1
2
3
4
使用next来遍历可迭代对象my_list
    print(next(my_list))
TypeError: 'MyList' object is not an iterator

从运行结果知道可迭代对象如果没有 __next__方法,则无法通过next()进行遍历。

创建一个生成器

像定义一般函数一样,只不过使用 yield 返回中间结果。生成器是一种特殊的迭代器,生成器自动实现了迭代器协议,即 __iter__ 和 __next__ 方法,不需要再手动实现两方法。创建生成器实例如下:

1  def myList(num):  # 定义生成器
2      now = 0  # 当前迭代值,初始为0
3      while now < num:
4          val = (yield now)  # 返回当前迭代值, 
5          now = now + 1 if val is None else val  # val为None,迭代值自增1,否则重新设定当前迭代值为val

遍历生成器:

1  my_list = myList(5)  # 得到一个生成器对象
2  print("for 循环遍历生成器myList")
3  for i in my_list:
4      print(i)
5  
6  my_list = myList(5)  # 得到一个生成器对象
7  print("next遍历生成器myList")
8  print(next(my_list))  # 返回当前迭代值值
9  print(next(my_list))  # 返回当前迭代值值
10  print(next(my_list))  # 返回当前迭代值值
11  print(next(my_list))  # 返回当前迭代值值
12  print(next(my_list))  # 返回当前迭代值值

运行结果如下:

for 循环遍历生成器myList
0
1
2
3
4
next遍历生成器myList
0
1
2
3
4

具有 yield 关键字的函数都是生成器,yield 可以理解为 return,返回后面的值给调用者。不同的是 return 返回后,函数会释放,而生成器则不会。在直接调用 next 方法或用 for 语句进行下一次迭代时,生成器会从 yield 下一句开始执行,直至遇到下一个 yield。

(完)

如果觉得这篇文章对您有帮助,请关注公众号 somenzz 及时获取最新消息或推荐给需要的朋友。


somenzz 的公众号

相关文章

  • Python基础-16生成器-迭代器

    16.生成器-迭代器     可循环迭代的对象称为可迭代对象,迭代器和生成器函数是可迭代对象,在Python中提供...

  • yield and Iterator

    Generator(生成器) 生成器是特殊的迭代器,迭代器不一定是生成器。 生成器与迭代器均是可迭代对象。 目前学...

  • Python中的迭代器和生成器

    今天我们来学习下Python中的迭代器和生成器。 迭代和可迭代对象 在学习迭代器之前,我们需要了解下迭代和可迭代对...

  • 理解迭代器/生成器

    完全理解Python 迭代对象、迭代器、生成器 迭代和生成操作总结 Python迭代器 http://www.ji...

  • 2-1迭代对象、迭代器、生成器

    可迭代对象、迭代器和生成器的关系 可迭代对象 可迭代对象实现某种接口,对与列表内部实现了__iter__()方法,...

  • Python可迭代对象,迭代器,生成器关系

    列表,元组,字符串,迭代器,生成器都是可迭代对象。所以,可迭代对象不一定是迭代器,生成器。 将一个可迭代对象传递给...

  • 迭代器、生成器和协程

    迭代器、生成器和协程 可迭代(Iterable) Python 中任意的对象, 只要定义了可以返回一个迭代器的 _...

  • 迭代器

    可迭代对象(Iterable): for迭代器(Iterator): for + next生成器属于迭代器。 验...

  • 可迭代对象、迭代器、生成器

    可迭代对象 --> 迭代器 --> 生成器; 可迭代对象:实现了__iter__()方法的对象,该方法返回迭代对象...

  • 3. Python 迭代器与生成器

    生成器与迭代器 迭代 迭代(Iteration)是一种遍历可迭代类型的方式 Python中通过for循环完成迭代 ...

网友评论

    本文标题:python 基础系列--可迭代对象、迭代器与生成器

    本文链接:https://www.haomeiwen.com/subject/bbvuaftx.html