How to unpack a tuple for looping without being dimension specific
<p>I'd like to do something like this:</p>

<pre><code>    if dim==2:
        a,b=grid_shape
        for i in range(a):
            for j in range(b):
                A[i,j] = ...things...
</code></pre>

<p>where <code>dim</code> is simply the number of elements in my tuple <code>grid_shape</code>. <code>A</code> is a numpy array of dimension <code>dim</code>.
Is there a way to do it without being dimension specific? 
Without having to write ugly code like </p>

<pre><code>    if dim==2:
        a,b=grid_shape
        for i in range(a):
            for j in range(b):
                A[i,j] = ...things...
    if dim==3:
        a,b,c=grid_shape
        for i in range(a):
            for j in range(b):
                for k in range(c):
                    A[i,j,k] = ...things...
</code></pre>

<p>Using itertools, you can do it like this:</p>

<pre><code>for index in itertools.product(*(range(x) for x in grid_shape)):
    A[index] = ...things...
</code></pre>

<p>This relies on a couple of tricks.  First, <code>itertools.product()</code> is a function which generates tuples from iterables.</p>

<pre><code>for i in range(a):
    for j in range(b):
        index = i,j
        do_something_with(index)
</code></pre>

<p>can be reduced to</p>

<pre><code>for index in itertools.product(range(a),range(b)):
    do_something_with(index)
</code></pre>

<p>This works for any number of arguments to <code>itertools.product()</code>, so you can effectively create nested loops of arbitrary depth.</p>

<p>The other trick is to convert your grid shape into the arguments for itertools.product:</p>

<pre><code>(range(x) for x in grid_shape)
</code></pre>

<p>is equivalent to</p>

<pre><code>(range(grid_shape[0]),range(grid_shape[1]),...)
</code></pre>

<p>That is, it is a tuple of ranges for each grid_shape dimension.  Using * then expands this into the arguments.</p>

<pre><code>itertools.product(*(range(x1),range(x2),...))
</code></pre>

<p>is equivalent to</p>

<pre><code>itertools.product(range(x1),range(x2),...)
</code></pre>

<p>Also, since <code>A[i,j,k]</code> is equivalent to <code>A[(i,j,k)]</code>, we can just use <code>A[index]</code> directly.</p>

<p>As <a href="http://stackoverflow.com/users/487339/dsm">DSM</a> points out, since you are using numpy, you can reduce</p>

<pre><code>itertools.product(*(for range(x) for x in grid_shape))
</code></pre>

<p>to</p>

<pre><code>numpy.ndindex(grid_shape)
</code></pre>

<p>So the final loop becomes</p>

<pre><code>for index in numpy.ndindex(grid_shape):
    A[index] = ...things...
</code></pre>

python loops numpy multidimensional-array tuples