只要你学了Python语言,就不会不知道for循环,也肯定用for循环来遍历一个列表(list),那为什么for循环可以遍历list,而不能遍历int类型对象呢?怎么让一个自定义的对象可遍历?
这篇博客中,我们来一起探索一下这个问题,在这个过程中,我们会介绍到迭代器、可迭代对象、生成器,更进一步的,我们会详细介绍他们的原理、异同。
2 迭代器与可迭代对象在开始下面内容之前,我们先说说标题中的“迭代”一词。什么是迭代?我认为,迭代一个完整过程中的一个重复,或者说每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,举一个类比来说:一个人类家族的发展是一个完整过程,需要经过数代人的努力,每一代都会以接着上一代的成果继续发展,所以每一代都是迭代。
2.1 迭代器(1)怎么判断是否可迭代
作为一门设计语言,Python提供了许多必要的数据类型,例如基本数据类型int、bool、str,还有容器类型list、tuple、dict、set。这些类型当中,有些是可迭代的,有些不可迭代,怎么判断呢?
在Python中,我们把所有可以迭代的对象统称为可迭代对象,有一个类专门与之对应:Iterable。所以,要判断一个类是否可迭代,只要判断是否是Iterable类的实例即可。
>>> from collections import Iterable >>> isinstance(123, Iterable) False >>> isinstance(True, Iterable) False >>> isinstance('abc', Iterable) True >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance((), Iterable) True
所以,整型、布尔不可迭代,字符串、列表、字典、元组可迭代。
怎么让一个对象可迭代呢?毕竟,很多时候,我们需要用到的对象不止Python内置的这些数据类型,还有自定义的数据类型。答案就是实现__iter__()方法,只要一个对象定义了__iter__()方法,那么它就是可迭代对象。
from collections.abc import Iterable class A(): def __iter__(self): pass print('A()是可迭代对象吗:',isinstance(A(),Iterable))
结果输出为:
A()是可迭代对象吗: True
瞧,我们在__iter__()方法里面甚至没写任何东西,反正我们在类A中定义则__iter__()方法,那么,它就是一个可迭代对象。
重要的事情说3遍:
只要一个对象定义了__iter__()方法,那么它就是可迭代对象。
只要一个对象定义了__iter__()方法,那么它就是可迭代对象。
只要一个对象定义了__iter__()方法,那么它就是可迭代对象。
2.2 迭代器迭代器是对可迭代对象的改造升级,上面说过,一个对象定义了__iter__()方法,那么它就是可迭代对象,进一步地,如果一个对象同时实现了__iter__()和__next()__()方法,那么它就是迭代器。
来,跟我读三遍:
如果一个对象同时实现了__iter__()和__next()__()方法,那么它就是迭代器。
如果一个对象同时实现了__iter__()和__next()__()方法,那么它就是迭代器。
如果一个对象同时实现了__iter__()和__next()__()方法,那么它就是迭代器。
在Python中,也有一个类与迭代器对应:Iterator。所以,要判断一个类是否是迭代器,只要判断是否是Iterator类的实例即可。
from collections.abc import Iterable from collections.abc import Iterator class B(): def __iter__(self): pass def __next__(self): pass print('B()是可迭代对象吗:',isinstance(B(), Iterable)) print('B()是迭代器吗:',isinstance(B(), Iterator))
结果输出如下:
B()是可迭代对象吗: True
B()是迭代器吗: True
可见,迭代器一定是可迭代对象,但可迭代对象不一定是迭代器。
所以整型、布尔一定不是迭代器,因为他们连可迭代对象都算不上。那么,字符串、列表、字典、元组是迭代器吗?猜猜!