Hettinger's iterator-with-sentinel

I just came across a beautiful technique to transform a function call to an iterator - Hettinger’s iterator-with-sentinel idiom.

most developers will probably write the following lines of code (including myself):

with open("file.data") as f:  
while True:
char = f.read(1)
if not char:
break
else:
# ...

A different, more elegant approach which uses Hettinger’s iterator-with-sentinel idiom:

from functools import partial

with open("file.data") as f:
for char in iter(partial(f.read, 1), ""):
# ...
  • The with-statement opens the file and unconditionally closes it when you’re finished.
  • The usual way to read one character is f.read(1).
  • The partial creates a function of zero arguments by always calling f.read with an argument of 1.
  • The two argument form of iter() creates an iterator that loops until you see the empty-string end-of-file marker

checkout this answer on stackoverflow that uses this idiom to decompress a gzip stream.