pythonにおける任意のネスト数のループ処理について


以下のような関数を作成したいと思っているのですが、任意の回数ループ処理を行う方法についてご教示賜りたいと存じます。

１．引数として、①任意の次元数のnumpy配列、②各次元に対応する処理を行う関数の２つをとる。  
②すべての配列要素に対して処理を行う。ただし、その処理は引数として指定した関数に基づく。

この時、任意の回数のネストした処理の作成方法がわかりません。  
例えば4次元配列なら、汚いですが

[code]

    x = NDARRAY.shape
    for i in range(x[0]):
        for j in range(x[1]):
            for k in range(x[2]):
                for l in range(x[3]):
    
[/code]

とでもできますが、一般にn次元の時、どのようにすればよいでしょうか。  
メタプログラミングの知識は必要でしょうか。




任意の深さのネストを再帰で表現した実装例です。  
**【実装例】**

[code]

    import numpy as np
    def looploop(func, na, dims=None, indexes=[], level=0, no=0, first=True):
        if dims is None:
            dims = na.shape
        if first:
            indexes = [0] * len(dims)
        if len(dims) <= 0:
            func(na, indexes)
            return
        for i in range(dims[0]):
            indexes[level] = i
            looploop(func, na, dims[1:], indexes=indexes, level=level+1, no=i, first=False)
    
    def func1(na, indexes):
        print("Hello:indexes=" + str(indexes))
    
    na = np.ndarray((2,3,4,5))
    
    looploop(func1, na)
    
[/code]

  * 処理名  
looploop

  * ①任意の次元数のnumpy配列  
na

  * ②各次元に対応する処理を行う関数  
func

  * funcの第１引数(numpy配列)  
na

  * funcの第２引数(インデックス)  
indexes

**【注意】**  
KLCさんの回答にある、多次元配列のデータを **１次元配列で管理した方が速度面で有利** だと思います。

【多次元】

[code]

    サイズ　     tttt[SIZE_1][SIZE_2][SIZE_3][SIZE_4]
    インデックス tttt[i1][i2][i3][i4]
    
[/code]

【１次元】

[code]

    サイズ　     t[SIZE_1 * SIZE_2 * SIZE_3 * SIZE_4]
    インデックス t[i]
    i = i1 * SIZE_2 * SIZE_3 * SIZE_4
      + i2 * SIZE_3 * SIZE_4
      + i3 * SIZE_4
      + i4
    
[/code]

iから各インデックスを求める場合は以下の式で計算します。

[code]

        i1 = (i % (SIZE_1 * SIZE_2 * SIZE_3 * SIZE_4)) // (SIZE_2 * SIZE_3 * SIZE_4)
        i2 = (i % (SIZE_2 * SIZE_3 * SIZE_4)) // (SIZE_3 * SIZE_4)
        i3 = (i % (SIZE_3 * SIZE_4)) // (SIZE_4)
        i4 = (i % SIZE_4)
    
[/code]

