Документация Python неофициальный перевод

timeit.md

218 строк · 15.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.1/library/timeit.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 26.4. `timeit` – измерение времени выполнения небольших фрагментов кода89Этот модуль предоставляет простой способ измерения времени выполнения небольших фрагментов кода Python. Он имеет как интерфейс командной строки, так и вызываемый интерфейс. Он позволяет избежать ряда распространённых ловушек при измерении времени выполнения. См. также введение Тима Питерса в главу «Алгоритмы» в книге Python Cookbook, опубликованной O’Reilly.1011Модуль определяет следующий открытый класс:1213#### `class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>)`1415Класс для измерения скорости выполнения небольших фрагментов кода.1617Конструктор принимает измеряемый оператор, дополнительный оператор, используемый для настройки, и функцию таймера. Оба оператора по умолчанию равны `'pass'`; функция таймера зависит от платформы (см. строку документации модуля). *stmt* и *setup* могут также содержать несколько операторов, разделённых `;` или символами новой строки, при условии, что они не содержат многострочных строковых литералов.1819Для измерения времени выполнения первого оператора используйте метод [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit). Метод [`repeat()`](https://python-all.ru/3.1/library/timeit.html#timeit.repeat) – это удобная функция для вызова [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit) несколько раз и возврата списка результатов.2021Параметры *stmt* и *setup* также могут принимать вызываемые объекты без аргументов. Это встраивает вызовы к ним в функцию таймера, которая затем выполняется с помощью [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit). Обратите внимание, что в этом случае накладные расходы на измерение времени немного выше из-за дополнительных вызовов функций.2223#### `Timer.print_exc(file=None)`2425Вспомогательная функция для вывода трассировки из кода, время выполнения которого измеряется.2627Типичное использование:2829```python30t = Timer(...)       # за пределами try/except31try:32    t.timeit(...)    # или t.repeat(...)33except:34    t.print_exc()35```3637Преимущество перед стандартным traceback в том, что будут отображаться строки исходного кода в скомпилированном шаблоне. Необязательный аргумент *file* определяет, куда отправляется traceback; по умолчанию он отправляется в `sys.stderr`.3839#### `Timer.repeat(repeat=3, number=1000000)`4041Вызывает [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit) несколько раз.4243Это удобная функция, которая многократно вызывает [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit), возвращая список результатов. Первый аргумент указывает, сколько раз вызывать [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit). Второй аргумент задаёт значение параметра *number* для [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit).4445> **Примечание**46>47> Может возникнуть соблазн вычислить среднее и стандартное отклонение из вектора результатов и сообщить их. Однако это не очень полезно. В типичном случае наименьшее значение даёт нижнюю границу того, насколько быстро ваша машина может выполнить данный фрагмент кода; более высокие значения в векторе результатов обычно вызваны не изменчивостью скорости Python, а другими процессами, мешающими точности измерения времени. Поэтому [`min()`](https://python-all.ru/3.1/library/functions.html#min) результатов – вероятно, единственное число, которое вас должно интересовать. После этого следует посмотреть на весь вектор и применить здравый смысл, а не статистику.4849#### `Timer.timeit(number=1000000)`5051Измеряет время выполнения *number* повторений основного оператора. Он выполняет оператор настройки один раз, а затем возвращает время, необходимое для выполнения основного оператора заданное число раз, измеряемое в секундах как число с плавающей запятой. Аргумент – это количество повторений цикла, по умолчанию один миллион. Основной оператор, оператор настройки и используемая функция таймера передаются конструктору.5253> **Примечание**54>55> По умолчанию [`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit) временно отключает [*сборку мусора*](https://python-all.ru/3.1/glossary.html#term-garbage-collection) во время измерения времени. Преимущество такого подхода в том, что он делает независимые измерения более сопоставимыми. Недостаток в том, что сборка мусора может быть важной составляющей производительности измеряемой функции. Если это так, сборку мусора можно снова включить, указав её в качестве первого оператора в строке *setup*. Например:56>57> ```python58> timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()59> ```6061Модуль также определяет две вспомогательные функции:6263#### `timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)`6465Создаёт экземпляр6667[`Timer`](https://python-all.ru/3.1/library/timeit.html#timeit.Timer)6869с указанным оператором, кодом настройки и функцией таймера и запускает его метод7071[`repeat()`](https://python-all.ru/3.1/library/timeit.html#timeit.repeat)7273с заданным количеством повторений и7475*number*7677выполнениями.7879#### `timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)`8081Создаёт экземпляр8283[`Timer`](https://python-all.ru/3.1/library/timeit.html#timeit.Timer)8485с указанным оператором, кодом настройки и функцией таймера и запускает его метод8687[`timeit()`](https://python-all.ru/3.1/library/timeit.html#timeit.timeit)8889с9091*number*9293выполнениями.9495## 26.4.1. Интерфейс командной строки9697При вызове как программы из командной строки используется следующая форма:9899```python100python -m timeit [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement ...]101```102103Где поддерживаются следующие параметры:104105#### `-n N, --number=N`106107сколько раз выполнять 'statement'108109#### `-r N, --repeat=N`110111сколько раз повторять таймер (по умолчанию 3)112113#### `-s S, --setup=S`114115оператор, выполняемый один раз вначале (по умолчанию116117`pass`118119)120121#### `-t, --time`122123использует124125[`time.time()`](https://python-all.ru/3.1/library/time.html#time.time)126127(по умолчанию на всех платформах, кроме Windows)128129#### `-c, --clock`130131использует132133[`time.clock()`](https://python-all.ru/3.1/library/time.html#time.clock)134135(по умолчанию в Windows)136137#### `-v, --verbose`138139выводить необработанные результаты замера; для большей точности (больше знаков) повторите параметр140141#### `-h, --help`142143вывести краткое сообщение об использовании и выйти144145Многострочный оператор можно задать, указав каждую строку как отдельный аргумент оператора; строки с отступами возможны, если заключить аргумент в кавычки и использовать начальные пробелы. Несколько параметров [*-s*](https://python-all.ru/3.1/library/timeit.html#cmdoption-timeit-s) обрабатываются аналогично.146147Если [*-n*](https://python-all.ru/3.1/library/timeit.html#cmdoption-timeit-n) не указан, подходящее количество циклов вычисляется путём последовательного перебора степеней 10, пока общее время не достигнет хотя бы 0,2 секунды.148149Функция таймера по умолчанию зависит от платформы. В Windows [`time.clock()`](https://python-all.ru/3.1/library/time.html#time.clock) имеет микросекундную точность, а [`time.time()`](https://python-all.ru/3.1/library/time.html#time.time) имеет точность 1/60 секунды; в Unix [`time.clock()`](https://python-all.ru/3.1/library/time.html#time.clock) имеет точность 1/100 секунды, а [`time.time()`](https://python-all.ru/3.1/library/time.html#time.time) гораздо точнее. На любой платформе функции таймера по умолчанию измеряют реальное время (wall clock time), а не процессорное время. Это означает, что другие процессы, работающие на том же компьютере, могут влиять на точность измерения. Лучшее, что можно сделать, когда требуется точное измерение, – это повторить измерение несколько раз и использовать наилучшее время. Опция [*-r*](https://python-all.ru/3.1/library/timeit.html#cmdoption-timeit-r) хорошо подходит для этого; значения по умолчанию в 3 повторения, вероятно, достаточно в большинстве случаев. В Unix вы можете использовать [`time.clock()`](https://python-all.ru/3.1/library/time.html#time.clock) для измерения процессорного времени.150151> **Примечание**152>153> Существует некоторая базовая накладная нагрузка, связанная с выполнением оператора pass. Приведённый код не пытается её скрыть, но следует знать об этом. Базовую накладную нагрузку можно измерить, вызвав программу без аргументов.154155Базовая накладная нагрузка отличается в разных версиях Python! Кроме того, для честного сравнения старых версий Python с Python 2.3 вы можете использовать опцию *-O* для старых версий, чтобы избежать измерения времени выполнения инструкций `SET_LINENO`.156157## 26.4.2. Примеры158159Вот два примера сеансов (один с использованием командной строки, другой с использованием интерфейса модуля), которые сравнивают стоимость использования [`hasattr()`](https://python-all.ru/3.1/library/functions.html#hasattr) против [`try`](https://python-all.ru/3.1/reference/compound_stmts.html#try)/[`except`](https://python-all.ru/3.1/reference/compound_stmts.html#except) для проверки отсутствующих и существующих атрибутов объектов.160161```python162% timeit.py 'try:' '  str.__bool__' 'except AttributeError:' '  pass'163100000 loops, best of 3: 15.7 usec per loop164% timeit.py 'if hasattr(str, "__bool__"): pass'165100000 loops, best of 3: 4.26 usec per loop166% timeit.py 'try:' '  int.__bool__' 'except AttributeError:' '  pass'1671000000 loops, best of 3: 1.43 usec per loop168% timeit.py 'if hasattr(int, "__bool__"): pass'169100000 loops, best of 3: 2.23 usec per loop170```171172```python173>>> import timeit174>>> s = """\175... try:176...     str.__bool__177... except AttributeError:178...     pass179... """180>>> t = timeit.Timer(stmt=s)181>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))18217.09 usec/pass183>>> s = """\184... if hasattr(str, '__bool__'): pass185... """186>>> t = timeit.Timer(stmt=s)187>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))1884.85 usec/pass189>>> s = """\190... try:191...     int.__bool__192... except AttributeError:193...     pass194... """195>>> t = timeit.Timer(stmt=s)196>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))1971.97 usec/pass198>>> s = """\199... if hasattr(int, '__bool__'): pass200... """201>>> t = timeit.Timer(stmt=s)202>>> print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000))2033.15 usec/pass204```205206Чтобы предоставить модулю `timeit` доступ к определённым вами функциям, вы можете передать параметр `setup`, содержащий инструкцию import:207208```python209def test():210    "Stupid test function"211    L = [i for i in range(100)]212213if __name__=='__main__':214    from timeit import Timer215    t = Timer("test()", "from __main__ import test")216    print(t.timeit())217```218