Раньше, когда мне требовались индексированные поисковые запросы с массивами в узком цикле, я обычно использую кортежи, поскольку они, как представляется, в целом чрезвычайно эффективны (близко к использованию только n-числа переменных). Тем не менее, я решил вопрос, что предположение сегодня и пришли к некоторым неожиданным результатам:Поиск списка быстрее, чем кортеж?
In [102]: l = range(1000)
In [103]: t = tuple(range(1000))
In [107]: timeit(lambda : l[500], number = 10000000)
Out[107]: 2.465047836303711
In [108]: timeit(lambda : t[500], number = 10000000)
Out[108]: 2.8896381855010986
кортежей поиски по всей видимости, займет 17% больше, чем список поисков! Аналогичные результаты дали повторные эксперименты. Дизассемблирование каждого, я нашел их, как быть:
In [101]: dis.dis(lambda : l[5])
1 0 LOAD_GLOBAL 0 (l)
3 LOAD_CONST 1 (5)
6 BINARY_SUBSCR
7 RETURN_VALUE
Для справки, типичный 10000000 глобальной переменной подстановки/возвращает принимать 2.2s. Кроме того, я запустил его без лямбда, а на всякий случай (обратите внимание, что число = 100 000 000, а не 10 000 000).
In [126]: timeit('t[500]', 't=range(1000)', number=100000000)
Out[126]: 6.972800970077515
In [127]: timeit('t[500]', 't=tuple(range(1000))', number=100000000)
Out[127]: 9.411366939544678
Здесь поиск по кортежам занимает 35% дольше. Что тут происходит? Для очень плотных циклов это действительно похоже на значительное несоответствие. Что может быть причиной этого?
Обратите внимание, что для разложения в переменную (например, x, y = t) кортежи немного быстрее (~ 6% в моих тестах меньше времени) и для построения из фиксированного числа аргументов кортежи сумасшедшие быстрее (~ На 83% меньше времени). Не принимайте эти результаты как общие правила; Я просто выполнил несколько minitests, которые будут бессмысленны для большинства проектов.
In [169]: print(sys.version)
2.7.1 (r271:86882M, Nov 30 2010, 09:39:13)
[GCC 4.0.1 (Apple Inc. build 5494)]
Я немного удивлен - хотя я не получаю 35% -ную разницу, которую вы утверждаете, ближе к 13%. –
Используете ли вы вызов функции или запускаете timeit со строками? Я приближаюсь к 13% (17%), если я заверну их в функции (см. Первый результат). Я думаю, что RETURN_VALUE и, возможно, LOAD_GLOBAL сближают значения. –
mac os x leopar, python 3.0, тот же код работает: 10.0xx для списка и 3.5xx для кортежа. – khachik