I'm assuming things like this are what you're talking about:
def lazy_product2(*args, repeat=1):
"recursive algorithm"
args = args * repeat
if not args:
yield ()
return
for all_but_last in lazy_product2(*args[:-1]):
for last in args[-1]():
yield all_but_last + (last,)
def lazy_product(*args, repeat=1):
"non-recursive algorithm"
funcs = args * repeat
iterators = [iter(f()) for f in funcs]
try:
result = [next(it) for it in iterators]
except StopIteration:
return
rev_range = range(len(iterators))[::-1]
sentinel = object()
while True:
yield tuple(result)
# get the next one
for i in rev_range:
result[i] = next(iterators[i], sentinel)
if result[i] is sentinel:
iterators[i] = iter(funcs[i]())
result[i] = next(iterators[i], sentinel)
if result[i] is sentinel:
# No new data this time around
return
else:
# stop "carrying", we incremented one.
# ready to yield.
break
else: # no break
return
import itertools
assert (list(lazy_product(lambda: range(3), lambda: range(2), repeat=2))
== list(itertools.product(range(3), range(2), repeat=2))
== list(lazy_product2(lambda: range(3), lambda: range(2),
repeat=2)))
infinite = lazy_product(itertools.count, lambda: "abc")
print([next(infinite) for i in range(10)])
# [(0, 'a'), (0, 'b'), (0, 'c'),
# (1, 'a'), (1, 'b'), (1, 'c'),
# (2, 'a'), (2, 'b'), (2, 'c'),
# (3, 'a')]
I think these don't generally fit with the "feel" of the itertools module
though since almost everything there accepts iterables and returns iterators,
and it's very focused on performance. Accepting no-arg callables that return
iterators doesn't feel like an obvious API to me. Another option is to accept
iterables that repeatedly get iter() called on them, but that's hard to make
work with generators, and people confuse iterables and iterators anyway, so
that might be too subtle. Maybe it's the sort of thing that just goes into a
personal library of small utility functions.
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/NZSUEF3EJNU7YOTEYH3GUFY7M3K4QT5M/
Code of Conduct: http://python.org/psf/codeofconduct/