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

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

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 循环。但了解之后,你会对代码理解得更透彻,同时这也是为我们后面要讲到的生成器做铺垫。




其他内容回复左侧关键词获取:

python :零基础入门课程目录

新手 :初学者指南及常见问题

资源 :超过500M学习资料网盘地址

项目 :十多个进阶项目代码实例


如需了解视频课程及答疑群等更多服务,请号内回复 码上行动

代码相关问题可以在论坛上发帖提问 bbs.crossincode.com

推荐阅读:

抖音 | AI名画 | 押韵工具 | 虎扑 | 如何debug | 查天气 | 我用Python | 知乎 | 排序 | 电影票 | 技术宅 | 单词表 | 新手建议 | 如何提问 | 中文编程

相关文章
|
2天前
|
Python 容器
python匿名函数、迭代器、高阶函数(二)
python匿名函数、迭代器、高阶函数(二)
|
2天前
|
索引 Python
python匿名函数、迭代器、高阶函数(一)
python匿名函数、迭代器、高阶函数(一)
|
13天前
|
缓存 大数据 数据处理
Python迭代器、生成器和装饰器探究
【4月更文挑战第2天】 迭代器是遍历集合元素的对象,实现`__iter__()`和`__next__()`方法。示例中自定义迭代器`MyIterator`用于生成整数序列。 - 生成器简化了迭代器实现,利用`yield`关键词实现状态保存,减少内存占用。示例中的`my_generator`函数即为一个生成器。 - 装饰器用于修改函数行为,如日志记录、性能分析。装饰器`my_decorator`在函数调用前后添加额外代码。
28 0
|
14天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
54 0
|
14天前
|
大数据 数据处理 开发者
深入理解Python中的迭代器和生成器
Python中的迭代器和生成器是实现高效循环和处理大型数据集的重要工具。本文将深入探讨迭代器和生成器的概念、原理以及在实际开发中的应用场景,帮助读者更好地理解和利用这些强大的工具。
|
14天前
|
缓存 算法 Python
python算法对音频信号处理Sonification :Gauss-Seidel迭代算法
python算法对音频信号处理Sonification :Gauss-Seidel迭代算法
10 0
|
15天前
|
Python
python学习12-类对象和实例对象
python学习12-类对象和实例对象
|
索引 Python
Python3快速入门——(7)迭代(iterable)和迭代器
迭代(iterable) #任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环 d = {'a': 1, 'b': 2, 'c': 3} #对dict迭代 for k,v in d.
1663 0
|
1天前
|
网络协议 算法 网络架构
Python网络编程之udp编程、黏包以及解决方案、tcpserver
Python网络编程之udp编程、黏包以及解决方案、tcpserver
|
1天前
|
机器学习/深度学习 数据挖掘 算法框架/工具
Python:编程的艺术与魅力
Python:编程的艺术与魅力
10 3