24

I often find myself doing this:

for x in range(x_size):
    for y in range(y_size):
        for z in range(z_size):
            pass # do something here

Is there a more concise way to do this in Python? I am thinking of something along the lines of

for x, z, y in ... ? :
Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
cacti
  • 475
  • 3
  • 15

4 Answers4

40

You can use itertools.product:

>>> for x,y,z in itertools.product(range(2), range(2), range(3)):
...     print x,y,z
... 
0 0 0
0 0 1
0 0 2
0 1 0
0 1 1
0 1 2
1 0 0
1 0 1
1 0 2
1 1 0
1 1 1
1 1 2
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • Thank you. I ended up going a different route as I can't use itertools, but, after reviewing the documentation for itertools, that is exactly what I needed. – cacti Dec 14 '12 at 23:00
  • It's worth noting that one of the great things about itertools.product is that it isn't creating the intermediate lists, which would involve lots of appends and behind the scenes array resizing and memory operations. Thus this version is not only elegant, but also faster and much easier on the garbage collector! If your nested loop is taking up a lot of your runtime when profiled this approach is worth trying. – Ezekiel Kruglick Aug 09 '15 at 05:47
8

If you've got numpy as a dependency already, numpy.ndindex will do the trick ...

>>> for x,y,z in np.ndindex(2,2,2):
...     print x,y,z
... 
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Hmm ... Apparently this does the same thing as `itertools.product`. Should have seen that one coming... :-) – mgilson Dec 14 '12 at 19:49
  • I like this solution! It is really concise, although it would be more a `numpy` idiom than a python idiom. – Bakuriu Dec 14 '12 at 19:54
  • 7
    @Bakuriu -- I come from the perspective that `python` without `numpy` is just a shiny toy ... But I know that's not everybody's perspective :-). – mgilson Dec 14 '12 at 19:59
7

Use itertools.product():

import itertools
for x, y, z in itertools.product(range(x_size), range(y_size), range(z_size)):
    pass # do something here

From the docs:

Cartesian product of input iterables.

Equivalent to nested for-loops in a generator expression.
...

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
0

It depends on what is inside the loop. If dealing with lists, you may be able to use a list comprehension

For the more general case, see this post on itertools.

Community
  • 1
  • 1
Jeanne Boyarsky
  • 12,156
  • 2
  • 49
  • 59