iter
iter()
函数用来生成迭代器,返回一个 iterator
对象。
iter(object[, sentinel])
根据是否存在第二个实参,第一个实参的解释是非常不同的。
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
具体为:
- 如果没有第二个实参,
object
必须是支持迭代协议(有__iter__()
方法)的集合对象,或必须支持序列协议(有__getitem__()
方法,且数字参数从 0 开始)。如果它不支持这些协议,会触发TypeError
。 - 如果有第二个实参
sentinel
,那么object
必须是可调用的对象。这种情况下生成的迭代器,每次迭代调用它的__next__()
方法时都会不带实参地调用object
;如果返回的结果是sentinel
则触发StopIteration
,否则返回调用结果。
适合 iter() 的第二种形式的应用之一是构建块读取器。 例如,从二进制数据库文件中读取固定宽度的块,直至到达文件的末尾:
from functools import partial
with open('mydata.db', 'rb') as f:
for block in iter(partial(f.read, 64), b''):
process_block(block)
partial(f.read, 64
等价于无参函数 lambda: f.read(64)
,每次循环读取文件 64 字节,当到达文件末尾 b''
时,触发 StopIteration
,结束循环( for 语句在序列为空或迭代器引发 StopIteration
异常时,结束循环)。
在看一个 chunk
函数例子:
from itertools import islice
def chunk(it, size):
"""分割it为等大小的chunk,每个chunk有size个元素,最后一个chunk 可能不足 size个"""
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())
>>> list(chunk(range(14), 3))
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]