#python #performance
Вопрос:
Я придумал кое — что довольно странное. Цель состоит в том, чтобы оценить длину итерации.
python -m timeit --setup="x = range(1000)" "x=list(x);len(x)"
1000000 циклов, лучшее из 3: 1,82 usec на цикл
python -m timeit --setup="x = range(1000)" "len(list(x))"
100000 циклов, лучшее из 3: 9,92 usec на цикл
Может ли кто — нибудь объяснить причину, по которой первый метод быстрее ?
Я попытался просмотреть инструкции по сборке, но это не помогает понять такое поведение.
С: x=list(x);len(x)
>>> dis.dis(meth1)
2 0 LOAD_GLOBAL 0 (list)
2 LOAD_FAST 0 (it)
4 CALL_FUNCTION 1
6 STORE_FAST 1 (x)
3 8 LOAD_GLOBAL 1 (len)
10 LOAD_FAST 1 (x)
12 CALL_FUNCTION 1
14 RETURN_VALUE
С len(list(x))
:
>>> dis.dis(meth2)
2 0 LOAD_GLOBAL 0 (len)
2 LOAD_GLOBAL 1 (list)
4 LOAD_FAST 0 (it)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 RETURN_VALUE
Комментарии:
1. Если этот вопрос действительно «почему meth2 быстрее», название не должно быть «самый быстрый способ». Если вопрос «самый быстрый способ», ответ @MartesBerkeley правильный, но не нужно беспокоиться о том, почему он быстрее. В любом случае, вопрос или заголовок нуждаются в редактировании
2. Вы правы, я изменил название
Ответ №1:
Вы должны учитывать тот факт, что настройка выполняется только один раз.
Испытание
--setup="x = range(1000)" "x=list(x);len(x)"
преобразует диапазон в список и сохраняет его обратно x
. Следующая итерация, это уже список, так что больше делать нечего.
Если вы измените это на другое имя переменной, разница должна исчезнуть:
--setup="x = range(1000)" "something=list(x);len(something)"
В другом тесте
--setup="x = range(1000)" "len(list(x))"
x
остается диапазоном и должен быть преобразован в список 100000 раз.
Комментарии:
1. Ты прав! Спасибо!