可迭代对象(Iterable)就是可以用 for 循环遍历的数据结构,包括字符串、元组、列表、字典、集合等内置类型,也可以通过一些方法来是实现自定义可迭代对象。
https://docs.python.org/3/glossary.html#term-iterable
https://docs.python.org/3/glossary.html#term-iterator
迭代协议与序列协议
-
迭代器协议(Iterator Protocol):如果一个对象包含
__next__
方法,那就是一个迭代器。迭代器可以使用
next
函数连续获取数据,内部实现就是调用__next__
方法获取一个数据项,如果循环结束,就会抛出StopIteration
。上面讲的是 CPython 实现,实际上 Python 语法规范要求迭代器一定要有
__iter__
方法。
一般实现中,都有加上__iter__
方法,直接return self
。 -
可迭代对象协议(Iterable Protocol):如果一个对象包含
__iter__
方法(返回一个迭代器对象),那么就是一个可迭代对象,可以用在 for 循环,
zip
,map
,filter
等需要可迭代对象的场景中。 -
序列对象协议(Sequence Protocol):如果一个对象包含
__getitem__
方法(使用 0 开始的整数作为索引),和__len__
方法,
就可以执行一些序列对象的操作,比如...(?)。
字符串,元组,列表都是序列对象。set 无序,dict 是按 key 索引,所以都不是序列对象。 -
迭代器协议(Iterator Protocol):如果一个对象包含
__iter__
方法,和__next__
方法,那就是一个迭代器。
迭代器可以使用next
函数连续获取数据,内部实现就是调用__next__
方法获取一个数据项,如果循环结束,就会抛出StopIteration
。
CPython 没有按照语言规范要求迭代器一定要有__iter__
方法。但一般实现中,都是加上__iter__
方法,return self
。
- https://docs.python.org/3/c-api/abstract.html
- Iterator Protocol https://docs.python.org/3/c-api/iter.html
- Sequence Protocol https://docs.python.org/3/c-api/sequence.html
iter
iter(iterable)
iter(callable, sentinel) # sentinel:任意值都行
iter(1)
TypeError: 'int' object is not iterable
iter(1, 1)
TypeError: iter(v, w): v must be callable
iter 用于生成一个迭代器。
- for 循环遍历的时候,会通过 iter 方法创建一个迭代器。
- 可以创建迭代器的对象,必须支持 iterable protocol (包含
__iter__()
方法),
或者支持 sequence protocol (包含__getitem__()
方法,使用 0 开始的整数作为索引)
原理
迭代器(Iterator)
迭代器是可迭代对象的一种。它是一个具有 __iter__()
和 __next__()
方法的对象,可以逐个返回可迭代对象的元素。
字符串、元组、列表、字典、集合这些内置类型就都不是迭代器。
PEP 234 – Iterators
https://peps.python.org/pep-0234/
自定义可迭代对象
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
self.index = 0
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
a = MyIterable(['apple', 'banana', 'cherry'])
for item in a:
print(item)