Welcome, guest | Sign In | My Account | Store | Cart

Same functionality as the itertools product method (http://docs.python.org/library/itertools.html#itertools.product) with one major difference: generators are executed as the loop executes. An itertools product causes all the variables to be collected before the loop actually starts looping.

Python, 41 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def recursiveLooper(iterators, pos=0):
    """ Implements the same functionality as nested for loops, but is 
        more dynamic. iterators can either be a list of methods which
        return iterables, a list of iterables, or a combination of both.
    """
    nextLoop, v = None, []
    try:
        gen = iter(iterators[pos]())
    except TypeError:
        gen = iter(iterators[pos])
        
    while True:
        try:
            yield v + nextLoop.next()
        except (StopIteration, AttributeError):
            v = [gen.next(),]
                
            if pos < len(iterators) - 1:
                nextLoop = recursiveLooper(iterators, pos + 1)
            else:
                yield v

# Some examples of how to use it:
def gen():
    for x in [1, 2]:
        yield x

for x in gen():
    for y in gen():
        for z in gen():
            print x, y, z

print "-" * 10

for x, y, z in recursiveLooper([gen,] * 3):
    print x, y, z

print "-" * 10

for x, y, z in recursiveLooper([[1, 2],] * 3):
    print x, y, z

2 comments

Daniel Lepage 11 years ago  # | flag

Actually, itertools.product doesn't collect the variables before looping. From http://docs.python.org/library/itertools.html#itertools.product: "the actual implementation does not build up intermediate results in memory".

Alexey Blinov 10 years, 11 months ago  # | flag

Its good as academic toy. But not very usefull in production. Because its very slow.

Nested loop:
  5.44 usec/pass
----------
recursiveLooper with gen() loop:
  103.70 usec/pass
----------
recursiveLooper with list loop:
  110.10 usec/pass
----------

And here is the code i used for this tests: http://pastie.textmate.org/1400002 Basically it's your code that is executed using timeit module (python standart module)

Created by Kieran on Fri, 1 Oct 2010 (MIT)
Python recipes (4591)
Kieran's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks