2013-06-28 38 views
0

我在使用此代碼時需要一些實際編碼,它需要封閉循環中的所有變量。我在想,如果迭代必須進行的範圍是相同的,那麼必須採用另一種方式,縮進和對所有變量的訪問權限相同。在Python中嵌套循環縮減的替代方案

是否有具有

  • 少縮進到這樣的嵌套循環的替代
  • 訪問變量以相同的順序在封閉範圍

的代碼:

import itertools 
import time 

#My Way 
s = time.time() 
sums_pyramid = [0] * 36 
for i in xrange(1,5): 
    for j in xrange(1,5): 
     for k in xrange(1,5): 
      for l in xrange(1,5): 
       for m in xrange(1,5): 
        for n in xrange(1,5): 
         for o in xrange(1,5): 
          for p in xrange(1,5): 
           for q in xrange(1,5): 
            sums_pyramid[i+j+k+l+m+n+o+p+q - 1] += 1 
print (time.time() - s) 


#Lattyware's suggested way 
s = time.time() 
sums_pyramid = [0] * 36 
for i,j,k,l,m,n,o,p,q in itertools.product(xrange(1,5), repeat = 9): 
    sums_pyramid[i+j+k+l+m+n+o+p+q - 1] += 1 
print (time.time() - s) 

時間結果

#My way 
0.259999990463 
#Lattyware's suggested way 
0.310000181198 

EDIT2:

後Lattyware建議,而不是使用time模塊,我應該使用timeit模塊我得到這些結果

新代碼:

import itertools 

def p(): 
    #My Way 
    sums_pyramid = [0] * 36 
    for i in xrange(1,5): 
     for j in xrange(1,5): 
      for k in xrange(1,5): 
       for l in xrange(1,5): 
        for m in xrange(1,5): 
         for n in xrange(1,5): 
          for o in xrange(1,5): 
           for p in xrange(1,5): 
            for q in xrange(1,5): 
             sums_pyramid[i+j+k+l+m+n+o+p+q - 1] += 1 


def q(): 
    #Lattyware's suggested way 
    sums_pyramid = [0] * 36 
    for i,j,k,l,m,n,o,p,q in itertools.product(xrange(1,5), repeat = 9): 
     sums_pyramid[i+j+k+l+m+n+o+p+q - 1] += 1 

if __name__ == '__main__': 
    times = 10 
    from timeit import Timer 
    print Timer(p, 'gc.enable()').timeit(number = times) 

    print Timer(q, 'gc.enable()').timeit(number = times) 

新的調速:

1.60324387493 
1.28266455309 

這些顯示Lattyware的代碼更好。

+2

問題是直接在列表後面的代碼 - 顯然,列表元素用於markdown中的其他內容之後的縮進。編輯修復。 –

回答

6

假設(如你的例子)這些循環都是獨立於父循環的,你需要itertools.product()

import itertools 

for i, j, k, l, m, n, o, p, q in itertools.product(xrange(1, 5), repeat=9): 
    ... 

這裏我使用了repeat關鍵字參數速記,在您的示例中,iterables都是相同的,但你也可以通過它的多個iterables如果您iterables都不盡相同。

它也會比許多嵌套循環更有效率。請注意,可能有更好的解決方案來解決您的問題 - 因爲迭代這麼多嵌套循環很可能是迭代量很大,因此非常緩慢。另外,如果你的循環依賴於它們的父循環或類似的東西(因爲product()不適合),你可以定義一些函數來採取一些繁重的嵌套並將其抽象出來。

for i in xrange(1,5): 
    for j in xrange(1,5): 
     for k in xrange(1,5): 
      for l in xrange(1,5): 
       for m in xrange(1,5): 
        inner_loops(i, j, k, l, m) 

def inner_loops(i, j, k, l, m): 
    for n in xrange(1,5): 
     for o in xrange(1,5): 
      for p in xrange(1,5): 
       for q in xrange(1,5): 
        pass 

這將超過product()表現更差,並且不太可讀的,但可能是必要的,視情況而定。自然地,您可以根據需要使用盡可能多的功能,以根據需要減少嵌套。作爲最後一點,我假設你使用範圍作爲一個簡單的例子,但是如果你打算使用索引來遍歷數據結構,那麼不要!它很難閱讀,不靈活和緩慢。直接在數據結構本身上循環 - 這些方法將以這種方式正常工作(實際上更好)。

+0

感謝您的回答。它確實幫助我提高了代碼的可讀性,減少了打字量。關於效率,你的建議效率稍低。我會更新問題以包含計時結果。 –

+0

如果從效率來說,你的意思是速度,那不應該是這樣 - product()在C代碼中進行更低級別的迭代(假設你正在使用CPython),而普通循環有更多的開銷,因爲它們是Python結構體。在時間不平凡的情況下,product()應該更快。 –

+0

我更新了問題以包含計時。 –