【Python 第75课】可迭代对象和迭代器

for 循环是我们在 Python 里非常常用的一个语法,但你有没有思考过 for 循环是怎样实现的?

如果你以前接触过 C++,应该会知道类似 for (int i = 0; i < 100; i++) 这样的写法,它定义了循环的执行条件 i < 100 以及每次循环结束后执行的语句 i++,而 for 本身只起到让代码重复执行的作用,并没有什么额外的功能。这在 Python 中其实更像是 while 循环:

i = 0
while i < 100:
   # 执行循环代码    i += 1

但 Python 里的 for 循环却不一样。使用 for 时,我们没有额外指定结束条件,也不需要一个用来计数的数值,甚至可以通过一个字符串进行循环。之所以可以这样,是因为 Python 中的迭代器(Iterator)以及可迭代对象(Iterable)

如果一个对象定义了 __iter____next__ 两个方法,它就是一个迭代器。对于迭代器来说,__iter__ 返回的是它自身 self__next__ 则是返回迭代器中的下一个值,如果没有值了则抛出一个 StopIteration 的异常。关于这点,你可以想象成一个只进不退的标记位,每次调用 __next__,就会将标记往后移一个元素并返回,直到结束。

有了迭代器的概念之后,如果一个对象定义了 __iter__ 和方法,返回一个迭代器对象,那么它就是一个可迭代的对象

从表现上来说,一个对象可迭代,那么它就可以被 for 循环使用。比如我们经常用到的 list、dict、str 等类型,都是可迭代的,所以也就可以通过 for 循环进行遍历,或者更准确的说:被迭代。

有一点绕,我们再来理一理迭代器(Iterator)和可迭代(Iterable)这两个的差别:

  1. 一个迭代器一定是可迭代对象,因为它一定有 __iter__ 方法。反过来则不成立。(事实上,Iterator 就是 Iterable 的子类)

  2. 迭代器的 __iter__ 方法返回的是自身,并不产生新实例。而可迭代对象的 __iter__ 方法通常会生成一个新的迭代器对象。

__iter____next__ 分别对应于 Python 的内置函数 iter()next():比如 iter(aList) 就相当于 aList.__iter__()

所以关于上述两点,我们可以有以下的例子来验证:

迭代器和可迭代之间的继承关系。

__iter__ 方法返回值的区别。id 相同代表是同一个实例。

明白了上述的概念之后,for 循环的实现就好理解了:

  1. 首先 for 循环会调用可迭代对象的 __iter__ 方法,获取相应的迭代器

  2. 每次循环,将迭代器的 __next__ 方法的返回值赋值给循环变量

  3. 直到捕获迭代器抛出的 StopIteration 异常,循环结束

再来看个例子:

思考题:想一想为什么迭代器 aListIter 被 for 循环迭代第二次的时候就没有输出了?

既然 __next__ 方法可以自己定义,我们也可以自己实现一个迭代器。比如要输出一个斐波那契数列(每一位数值都是前两位数值之和,原题回复关键字 906),通常的做法是循环,“高级”一点的做法是递归。但我们也可以直接写一个斐波那契迭代器:

# 定义迭代器
class Fibonacci():    def __init__(self):        self.a = 0        self.b = 1    def __iter__(self):        return self
   def __next__(self):        # 结束条件        if self.b > 100:
           raise StopIteration
       # 更新一次数值        self.a, self.b = self.b, self.a + self.b
       return self.a
# 创建迭代器
fib = Fibonacci()
# 进行迭代
for f in fib:    print(f, end=' ')

输出:

1 1 2 3 5 8 13 21 34 55 89

这个例子中,我们并没有保存一个序列,只是定义了一种规则,就也可以被迭代。

使用迭代器的好处在于:它是一种延迟操作,即当需要用到的时候才去产生结果。比如对于一个序列来说,如果我们要遍历它,并不需要再一开始就把所有元素都生成好,而是只需要知道每个元素的下一个元素是什么就可以了。这样可以节省很多空间,尤其对于数量很大的集合来说。

如果你不懂迭代器的概念,并不影响在代码中使用 for 循环。但了解之后,你会对代码理解得更透彻,同时这也是为我们后面要讲到的生成器做铺垫。

(0)

相关推荐

  • Python学习——for循环,生成器,迭代器详解

    文章目录 Python的for循环 for循环示例 List 列表循环 dict 字典循环 列表生成式 生成器 列表式生成器 函数式生成器 生成器式生产者消费者模型 迭代器 什么是迭代器 再论for循 ...

  • Python迭代器

    迭代器是可以迭代的对象. 在本教程中,您将了解迭代器的工作原理,以及如何使用__iter__和__next__方法构建自己的迭代器. 迭代器在Python中无处不在. 它们优雅地实现在循环,推导,生成 ...

  • 面试题-python 什么是迭代器?

    前言 python 里面有 3 大神器:迭代器,生成器,装饰器.在了解迭代器之前,需弄清楚2个概念: 1.什么是迭代 2.什么是可迭代对象 迭代 如果给定一个list或tuple,我们可以通过for循 ...

  • 一文掌握 Python 迭代器的原理

    理解迭代器是每个严肃的 Python 使用者学习 Python 道路上的里程碑.本文将从零开始,一步一步带你认识 Python 中基于类的迭代器. 相较于其他编程语言,Python 的语法是优美而清晰 ...

  • Python学习之迭代器和生成器有什么不同?

    迭代器和生成器区别是什么?相信很多人在初学Python的时候对它们都很好奇,接下来我们一起来看看它们的区别吧. 迭代器是一个更抽象的概念,任何对象,如果它的类有next方法和iter方法返回自己的本身 ...

  • 一文读懂Python可迭代对象、迭代器和生成器

    IT头条 每日推送最新.最热点的IT界新闻 马化腾回应"腾讯没有梦想"截图系网友PS:天天P图回应<我的前世青年照>涉嫌收集个人隐私:马云称阿里不愿招北大清华毕业生-- ...

  • Python中可迭代对象怎么获取迭代器?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  • C# 便捷实现可迭代对象间的赋值

    问题起源于本人的一个练手的扑克牌程序:洗完牌之后要发给场上的三人. 只发给单个人的时候用 foreach 循环一下就好了,但三个人就有点麻烦了. 牌组用list保存你可能会想到这样写: for (in ...

  • 【Python 第74课】多线程

    很多人使用 python 编写"爬虫"程序,抓取网上的数据. 举个例子,通过豆瓣的 API 抓取 30 部影片的信息: import urllib, time time_start ...

  • 学Python编程数据分析课就能解决职场焦虑吗?

    Python是当下最流行的编程语言之一. 目前它在中国已经渗透到了各行各业.最明显的迹象是,在微信朋友圈里,与Python相关的编程课推送变得越来越多. 在微信朋友圈的广告中,Python被宣传为&q ...

  • 几何画板 第5课:迭代和深度迭代

    几何画板 第5课:迭代和深度迭代

  • python语法第二课《程序中的注释》

    https://m.toutiao.com/is/J7gGBCJ/ 看完美女后学习! 刚开始学程序时,就要有一个良好的编程习惯~写注释!写注释!写注释! 注释就是一种说明,用一种直白的方法告诉其他人你 ...

  • 一课一题一语法:新概念英语第2册第75课

    [往期回顾] 一课一题一语法:新概念英语第2册第74课 [答案] 1. If he _goes_ (go) there next week, I _will go_ (go) with him. 2. ...

  • 《新概念英语》朗读技巧:第1册第75课

    [往期回顾] <新概念英语>朗读技巧:第1册第73课 [本期内容] 一.课文原文 大家可以从下面购买<新概念英语>第一册的官方教材: 二.廖老师点拨 1. LADY: Do y ...