from collections.abc import Iterable, Iterator class _ZipSentinel: pass _ZIP_SENTINEL: _ZipSentinel = _ZipSentinel() def zip_n(*iterables: Iterable, n: int) -> Iterator[tuple]: n = max(n, 0) if len(iterables) == 0: for i in range(n): yield () return iterators = list(map(iter, iterables)) for i in range(n): tup = tuple(next(it, _ZIP_SENTINEL) for it in iterators) if any(isinstance(v, _ZipSentinel) for v in tup): raise ValueError(f"at least one of iterables was exhausted in {i + 1} < {n} iterations") yield tup