iter

iter() 函数用来生成迭代器,返回一个 iterator 对象。

  1. iter(object[, sentinel])

根据是否存在第二个实参,第一个实参的解释是非常不同的。

  1. iter(iterable) -> iterator
  2. iter(callable, sentinel) -> iterator

具体为:

  • 如果没有第二个实参, object 必须是支持迭代协议(有 __iter__() 方法)的集合对象,或必须支持序列协议(有 __getitem__() 方法,且数字参数从 0 开始)。如果它不支持这些协议,会触发 TypeError
  • 如果有第二个实参 sentinel ,那么 object 必须是可调用的对象。这种情况下生成的迭代器,每次迭代调用它的 __next__() 方法时都会不带实参地调用 object ;如果返回的结果是 sentinel 则触发 StopIteration ,否则返回调用结果。

适合 iter() 的第二种形式的应用之一是构建块读取器。 例如,从二进制数据库文件中读取固定宽度的块,直至到达文件的末尾:

  1. from functools import partial
  2. with open('mydata.db', 'rb') as f:
  3. for block in iter(partial(f.read, 64), b''):
  4. process_block(block)

partial(f.read, 64 等价于无参函数 lambda: f.read(64) ,每次循环读取文件 64 字节,当到达文件末尾 b'' 时,触发 StopIteration ,结束循环( for 语句在序列为空或迭代器引发 StopIteration 异常时,结束循环)。
在看一个 chunk 函数例子:

  1. from itertools import islice
  2. def chunk(it, size):
  3. """分割it为等大小的chunk,每个chunk有size个元素,最后一个chunk 可能不足 size个"""
  4. it = iter(it)
  5. return iter(lambda: tuple(islice(it, size)), ())
  1. >>> list(chunk(range(14), 3))
  2. [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13)]

参考