Разница во времени между двумя одинаковыми методами для получения длины повторяемой

#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. Ты прав! Спасибо!