Сохранить память для списка в Python?
При программировании на Python можно зарезервировать память для списка, который будет заполнен известным количеством элементов, чтобы список не перераспределялся несколько раз при его создании? Я просмотрел документы для типа списка Python и не нашел ничего похожего на это. Тем не менее, этот тип создания списка отображается в нескольких горячих точках моего кода, поэтому я хочу сделать его максимально эффективным.
Edit: Кроме того, имеет ли смысл делать что-то подобное на языке Python? Я довольно опытный программист, но новичок в Python и все еще чувствую, как он работает. Является ли Python внутренне выделять объекты all в отдельных пространствах кучи, преуменьшая цель попытки свести к минимуму выделения или примитивы, такие как int, float и т.д., Хранящиеся непосредственно в списках?
Ответы
Ответ 1
Здесь четыре варианта:
- создание инкрементного списка
- "предварительно выделенный" список
- array.array()
- numpy.zeros()
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
Это показывает, что [None]*N
является самым быстрым, а array.array
является самым медленным в этом случае.
Ответ 2
вы можете создать список известной длины следующим образом:
>>> [None] * known_number
Ответ 3
Взгляните на это:
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])*N
или numpy.zeros
.
Ответ 4
В большинстве повседневных кодов вам не нужна такая оптимизация.
Однако, когда эффективность списков становится проблемой, первое, что вам нужно сделать, это заменить общий список с помощью типичного из array
module, который гораздо эффективнее.
Здесь создается список из 4 миллионов чисел чисел с плавающей запятой:
import array
lst = array.array('f', [0.0]*4000*1000)
Ответ 5
Если вы хотите эффективно управлять числами в Python, посмотрите на NumPy (
http://numpy.scipy.org/). Это позволяет вам делать что-то очень быстро, продолжая использовать Python.
Чтобы сделать то, что вы задали в NumPy, вы бы сделали что-то вроде
import numpy as np
myarray = np.zeros(4000)
который даст вам массив чисел с плавающей запятой, инициализированных до нуля. Затем вы можете сделать очень классные вещи, например, умножить целые массивы на один фактор или на другие массивы и другие вещи (вроде как в Matlab, если вы когда-либо использовали это), что очень быстро (большая часть фактической работы происходит в высоко оптимизированная часть C библиотеки NumPy).
Если это не массивы чисел, то после этого вы, вероятно, не найдете способ сделать то, что хотите в Python. Список объектов Python - это список точек объектов внутри (я так думаю, я не специалист по внутренности Python), поэтому он все равно будет выделять каждый из его членов при их создании.
Ответ 6
В Python все объекты выделены в куче.
Но Python использует специальный распределитель памяти, поэтому malloc
не будет вызываться каждый раз, когда вам нужен новый объект.
Существуют также некоторые оптимизации для небольших целых чисел (и т.п.), которые кэшируются; однако, какой тип и каким образом зависит от реализации.
Ответ 7
для Python3:
import timeit
from numpy import zeros
from array import array
def func1():
N=10**6
a = []
app = a.append
for i in range(N):
app(i)
def func2():
N=10**6
a = [None]*N
app = a.append
for i in range(N):
a[i] = i
def func3():
N=10**6
a = array('i', [0]*N)
for i in range(N):
a[i] = i
def func4():
N=10**6
a = zeros(N,dtype='i')
for i in range(N):
a[i] = i
start_time = timeit.default_timer()
func1()
print(timeit.default_timer() - start_time)
start_time = timeit.default_timer()
func2()
print(timeit.default_timer() - start_time)
start_time = timeit.default_timer()
func3()
print(timeit.default_timer() - start_time)
start_time = timeit.default_timer()
func4()
print(timeit.default_timer() - start_time)
результат:
0.1655518
0.10920069999999998
0.1935983
0.15213890000000002
- добавление()
- [Отсутствует] * N
- используя массив модулей
- используя модуль NumPy