for 循环 是我们在 Python 里非常常用的一个语法,但你有没有思考过 for 循环是怎样实现的?如果你以前接触过 C++,应该会知道类似 for (int i = 0; i < 100; i++) 这样的写法,它定义了 循环的执行条件 i < 100 以及 每次循环结束后执行的语句 i++,而 for 本身只起到让代码重复执行的作用,并没有什么额外的功能。这在 Python 中其实更像是 while 循环: i = 0while i < 100: # 执行循环代码 i += 1但 Python 里的 for 循环却不一样。使用 for 时,我们没有额外指定结束条件,也不需要一个用来计数的数值,甚至可以通过一个字符串进行循环。之所以可以这样,是因为 Python 中的 迭代器(Iterator) 以及 可迭代对象(Iterable) 。如果一个对象定义了 iternext 两个方法, 它就是一个迭代器 。对于迭代器来说,iter 返回的是它自身 self ,next 则是 返回迭代器中的下一个值 ,如果没有值了则抛出一个 StopIteration 的异常。关于这点,你可以想象成一个只进不退的标记位,每次调用 next,就会将标记往后移一个元素并返回,直到结束。有了迭代器的概念之后,如果一个对象定义了 iter 和方法,返回一个迭代器对象,那么 它就是一个可迭代的对象 。从表现上来说,一个对象 可迭代 ,那么它就可以被 for 循环使用。比如我们经常用到的 list、dict、str 等类型,都是可迭代的,所以也就可以通过 for 循环进行遍历,或者更准确的说:被迭代。有一点绕,我们再来理一理迭代器(Iterator)和可迭代(Iterable)这两个的差别:一个 迭代器一定是可迭代对象 ,因为它一定有 iter 方法。反过来则不成立。(事实上,Iterator 就是 Iterable 的子类)迭代器的 iter 方法 返回的是自身,并不产生新实例 。而可迭代对象的 iter 方法通常会生成一个新的迭代器对象。iternext 分别对应于 Python 的内置函数 iter() 和 next():比如 iter(aList) 就相当于 aList.iter()。所以关于上述两点,我们可以有以下的例子来验证:迭代器和可迭代之间的继承关系。iter 方法返回值的区别。id 相同代表是同一个实例。明白了上述的概念之后,for 循环的实现就好理解了:首先 for 循环会调用可迭代对象的 iter 方法,获取相应的迭代器每次循环,将迭代器的 next 方法的返回值赋值给循环变量直到捕获迭代器抛出的 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 循环。但了解之后,你会对代码理解得更透彻,同时这也是为我们后面要讲到的 生成器 做铺垫。════其他文章及回答:如何自学Python | 新手引导 | 精选Python问答 | Python单词表 | 人工智能 | 爬虫 | 我用Python | requests | 计算机视觉 | 字符播放器 | 一图学Python欢迎搜索及关注公众号: Crossin的编程教室