>>> from itertools import chain >>> >>> class TestCM: ... def __init__(self, it): ... self.it = it ... def __enter__(self): ... print('entering cm for', self.it) ... return self ... def __exit__(self, exc_type, exc_val, exc_tb): ... print('exiting cm for', self.it) ... def __iter__(self): ... yield from self.it ... >>> >>> def itercm(cm): ... with cm: ... yield from cm ... >>> seq = (itercm(TestCM(s)) for s in ['foo', 'bar', 'baz']) >>> for c in chain.from_iterable(seq): ... print(c) ... entering cm for foo f o o exiting cm for foo entering cm for bar b a r exiting cm for bar entering cm for baz b a z exiting cm for baz >>> >>> >>> # exit is called in case of errors >>> seq = (itercm(TestCM(s)) for s in ['foo', ('a', 3), 'baz']) >>> for c in chain.from_iterable(seq): ... print(c.upper()) ... entering cm for foo F O O exiting cm for foo entering cm for ('a', 3) A exiting cm for ('a', 3) Traceback (most recent call last): File "", line 2, in AttributeError: 'int' object has no attribute 'upper' >>> >>> >>> import re >>> >>> def grep(pattern, fnames): ... lines = chain.from_iterable(itercm(open(f)) for f in fnames) ... matches = (line for line in lines if re.search(pattern, line)) ... for line in matches: ... print(line, end='') ... >>> grep('^def', ['itercm.py']*3) def itercm(cm): def grep(pattern, fnames): def itercm(cm): def grep(pattern, fnames): def itercm(cm): def grep(pattern, fnames): >>>