Bob Ippolito (@etrepum) on Haskell, Python, Erlang, JavaScript, etc.
«

Python iterators and sentinel values

»

A little known feature of PEP 234: Iterators (implemented in Python 2.1 and later) is the alternate form:

iter(callable, sentinel)

This form creates an iterator out of any callable, and will stop when an exception is raised or the sentinel value is returned by the callable. Additionally, raising StopIteration will stop the iteration as with a normal iterator. A sentinel value is a special value that indicates the end of a sequence. This can be any value, but the most commonly useful values are likely to be None, 0, or ''.

I haven't seen much code in the wild that takes advantage of this form of iter, but an excellent usage would be to replace this common idiom:

while True:
    data = fileobj.read(BLOCKSIZE)
    if not data:
        break
    # do something with data here

Using the sentinel form of iter, it can be rewritten as an iterator with more obvious control flow:

for data in iter(lambda: fileobj.read(BLOCKSIZE), ''):
    # do something with data here

Of course, nobody likes a lambda, but you could wrap this up as a little utility function, or you could wait for PEP 309: Partial Function Application (on the standards track, will be in Python 2.5). With partial it would look like this:

for data in iter(partial(fileobj.read, BLOCKSIZE), ''):
    # do something with data here