2009-02-11 90 views
37

當Python編程,是有可能保留內存,以便將與已知數量的項目填充一個列表,以便同時建立它的列表將不會被重新分配幾次?我已經瀏覽了Python列表類型的文檔,並沒有發現任何似乎這樣做的內容。然而,這種類型的列表建築出現在我的代碼的幾個熱點中,所以我想盡可能提高效率。爲Python中的列表保留內存?

編輯:另外,它甚至是有意義的做這樣的事情在像Python語言?我是一個相當有經驗的程序員,但是對於Python來說是新手,並且仍然感受到它的做事方式。是否Python的內部分配在單獨的堆空間都對象,擊敗試圖最小化分配的目的,或像元整數,浮點數等直接存儲在列表中?

+0

不要過早優化。 – ironfroggy 2010-01-31 15:19:52

+20

@ironfroggy:重點是,這**出現在熱點**。在這些地方,名單建設造成了**重大的現實世界的瓶頸**,這是您應該優化的那種。 – dsimcha 2010-01-31 16:36:29

+0

可能重複[Python - 創建一個具有初始容量的列表](http://stackoverflow.com/questions/311775/python-create-a-list-with-initial-capacity) – 2015-05-06 04:28:25

回答

30

這裏有四種形式:

  • 增量列表創建
  • 「預分配」 列表
  • array.array()
  • numpy的。零()

 

python -mtimeit -s"N=10**6" "a = []; app = a.append;"\ 
    "for i in xrange(N): app(i);" 
10 loops, best of 3: 390 msec per loop 

python -mtimeit -s"N=10**6" "a = [None]*N; app = a.append;"\ 
    "for i in xrange(N): a[i] = i" 
10 loops, best of 3: 245 msec per loop 

python -mtimeit -s"from array import array; N=10**6" "a = array('i', [0]*N)"\ 
    "for i in xrange(N):" " a[i] = i" 
10 loops, best of 3: 541 msec per loop 

python -mtimeit -s"from numpy import zeros; N=10**6" "a = zeros(N,dtype='i')"\ 
    "for i in xrange(N):" " a[i] = i" 
10 loops, best of 3: 353 msec per loop 

它表明​​是最快和array.array是在這種情況下最慢。

12

你可以這樣創建已知長度的名單:

>>> [None] * known_number 
5

在最日常的代碼,你不會需要這樣的優化。

然而,當列表效率就成了一個問題,你應該做的第一件事就是更換輸入一個從array module這是更爲有效的泛型列表。

下面是400萬浮點數cound列表創建:

import array 
lst = array.array('f', [0.0]*4000*1000) 
+2

你是什麼意思「更多高效「? `array.array`可能需要更少的內存,但是Python列表在大多數情況下(意思是我嘗試過的)情況更快。 – jfs 2009-02-11 15:24:48

+4

在這種情況下,它甚至會首先創建一個列表,然後從列表中創建一個數組。這不是有效的。 – 2009-02-11 15:52:19

2

在Python中,所有的對象都是在堆上分配。
,而Python用一種特殊的內存分配器等等malloc不會被調用每次你需要一個新的對象時。
對於緩存的小整數(等等)也有一些優化;然而,哪些類型以及如何依賴於實現。

4

如果你想在Python中有效地操縱數字,那麼看看NumPy( http://numpy.scipy.org/)。它讓你在非常快速的情況下完成任務,同時仍然可以使用Python。

做什麼你在與NumPy問你會做這樣的事情

import numpy as np 
myarray = np.zeros(4000) 

這將使你的浮動初始化爲零點數的數組。然後,你可以做很酷的事情,比如用單一因子或其他數組和其他數組(如果你曾經使用過這種類型,就像在Matlab中那樣)乘以整個數組,這是非常快的(大部分實際工作發生在高度優化的NumPy庫的C部分)。

如果不是數字的數組你那麼之後你可能不會找到一種方法,你在Python想要什麼。對象的Python列表是指向內部對象的列表(我認爲無論如何,我不是Python內部專家),因此它在創建它們時仍將分配其每個成員。

8

在此請看:

In [7]: %timeit array.array('f', [0.0]*4000*1000) 
1 loops, best of 3: 306 ms per loop 

In [8]: %timeit array.array('f', [0.0])*4000*1000 
100 loops, best of 3: 5.96 ms per loop 

In [11]: %timeit np.zeros(4000*1000, dtype='f') 
100 loops, best of 3: 6.04 ms per loop 

In [9]: %timeit [0.0]*4000*1000 
10 loops, best of 3: 32.4 ms per loop 

所以永遠不要使用array.array('f', [0.0]*N),用array.array('f', [0.0])*Nnumpy.zeros