Я недавно изучаю Python и много практикуюсь с языком.

Одна вещь, которая мне показалась интересной, это то, что когда я читаю из массива, он почти в два раза медленнее, чем список. Кто-нибудь знает почему?

Вот мой код:

from timeit import Timer
import array

t = 10000
l = range(t)
a = array.array('i', l)
def LIST():
    for i in xrange(t):
        l[i]

def ARRAY():
    for i in xrange(t):
        a[i]

print Timer(LIST).timeit(1000);
print Timer(ARRAY).timeit(1000);

Вывод:

0.813191890717
1.16269612312

Что указывает на то, что массив чтения медленнее, чем список. Я думаю, что массив - это память фиксированного размера, а список - это динамическая структура. Поэтому я предположил, что массив будет быстрее, чем список.

Есть ли у кого-нибудь объяснения?

9
FrostNovaZzz 17 Июл 2010 в 18:13

3 ответа

Лучший ответ

Требуется время, чтобы обернуть необработанное целое число в Python int.

8
kennytm 17 Июл 2010 в 14:17

Списки Python действительно похожи на обычные массивы, они не являются списками Lisp, но имеют быстрый произвольный доступ.

1
Tony Veijalainen 17 Июл 2010 в 14:32

list являются "динамически растущими векторами" (скажем, очень похожи на std::vector в C ++), но это никоим образом не замедляет произвольный доступ к ним (это не списки связанных ! -) . Записи списков являются ссылками на объекты Python (элементы): для доступа к ним просто требуется (в CPython) увеличение счетчика ссылок на элементы (в других реализациях, основанных на более продвинутой сборке мусора, даже не на этом ;-). Записи массива представляют собой необработанные биты и байты: для доступа к ним требуется синтезировать новый объект Python на основе этого двоичного значения. Так, например:

$ python -mtimeit -s'import array; c=array.array("B", "bzap")' 'c[2]'
10000000 loops, best of 3: 0.0903 usec per loop
$ python -mtimeit -s'c=list("bzap")' 'c[2]'
10000000 loops, best of 3: 0.0601 usec per loop

Дополнительное время доступа в 30 наносекунд не кажется слишком плохим ;-).

Кроме того, обратите внимание, что timeit НАМНОГО лучше использовать из командной строки - автоматический выбор повторения, единица измерения, показываемая для времени, и т. Д. Вот как я всегда использую это (импорт модуля с пользовательским кодом) с функциями, которые нужно вызывать, если необходимо - но здесь в этом нет необходимости) - это так намного удобнее, чем импортировать и использовать его из модуля!

9
Alex Martelli 17 Июл 2010 в 15:48