Python Timeit を使用してコードの時間を計る

公開: 2023-01-17

このチュートリアルでは、Python の timeit モジュールから timeit 関数を使用する方法を学習します。 Python で単純な式と関数の時間を計測する方法を学習します。

コードのタイミングを計ると、コードの一部の実行時間の見積もりを取得したり、最適化が必要なコードのセクションを特定したりするのに役立ちます。

Python のtimeit関数の構文を学習することから始めます。 次に、コード例をコーディングして、それを使用して Python モジュールのコードと関数のブロックの時間を計る方法を理解します。 さぁ、始めよう。

Python timeit 関数の使用方法

timeitモジュールは Python 標準ライブラリの一部であり、インポートできます。

 import timeit

timeitモジュールのtimeit関数を使用する構文は次のとおりです。

 timeit.timeit(stmt, setup, number)

ここに:

  • stmtは、実行時間を測定するコードです。 単純な Python 文字列または複数行の文字列として指定するか、callable の名前を渡すことができます。
  • 名前が示すように、 setupは、多くの場合、 stmtを実行するための前提条件として、1 回だけ実行する必要があるコードの一部を示します。 たとえば、NumPy 配列の作成の実行時間を計算しているとします。 この場合、 numpyのインポートはsetupコードであり、実際の作成は時間を計るステートメントです。
  • パラメータnumberは、 stmtが実行される回数を示します。 numberのデフォルト値は 100 万 (1000000) ですが、このパラメーターを任意の他の値に設定することもできます。

timeit()関数を使用する構文を学習したので、いくつかの例のコーディングを開始しましょう。

単純な Python 式のタイミング

Timing-Simple-Python-式

このセクションでは、timeit を使用して単純な Python 式の実行時間を測定してみます。

Python REPL を開始し、次のコード例を実行します。 ここでは、10000 回と 100000 回の実行に対するべき乗と床除算演算の実行時間を計算しています。

Python 文字列としてタイミングを取るステートメントを渡し、セミコロンを使用してステートメント内の異なる式を区切っていることに注意してください。

 >>> import timeit >>> timeit.timeit('3**4;3//4',number=10000) 0.0004020999999738706 >>> timeit.timeit('3**4;3//4',number=100000) 0.0013780000000451764

コマンド ラインでの Python timeit の実行

コマンド ラインでtimeitを使用することもできます。 timeit 関数呼び出しに相当するコマンド ラインを次に示します。

 $ python-m timeit -n [number] -s [setup] [stmt]
  • python -m timeitは、 timeitをメイン モジュールとして実行することを表します。
  • nは、コードを実行する回数を示すコマンド ライン オプションです。 これは、 timeit()関数呼び出しのnumber引数に相当します。
  • オプション-sを使用して、セットアップ コードを定義できます。

ここでは、同等のコマンドラインを使用して前の例を書き直します。

 $ python -m timeit -n 100000 '3**4;3//4' 100000 loops, best of 5: 35.8 nsec per loop

この例では、組み込みのlen()関数の実行時間を計算します。 文字列の初期化は、 sオプションを使用して渡されるセットアップ コードです。

 $ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)' 100000 loops, best of 5: 239 nsec per loop

出力では、ベスト オブ 5の実行の実行時間が取得されていることに注意してください。 これは何を意味するのでしょうか? コマンド ラインでtimeitを実行すると、 repeatオプションrデフォルト値の 5 に設定されます。これは、指定されたnumberstmtの実行が 5 回繰り返され、最良の実行時間が返されることを意味します。

timeit を使用した文字列反転メソッドの分析

Python 文字列を操作する場合、それらを逆にしたい場合があります。 文字列反転の最も一般的な 2 つの方法は次のとおりです。

  • 文字列スライスの使用
  • reversed()関数とjoin()メソッドの使用
timeit を使用した文字列反転メソッドの分析

文字列スライスを使用した Python 文字列の反転

文字列スライスの仕組みと、それを使用して Python 文字列を逆にする方法について説明しましょう。 構文some-string[start:stop]を使用すると、インデックスstartからインデックスstop-1までの文字列のスライスが返されます。 例を見てみましょう。

次の文字列「Python」を考えてみましょう。 文字列の長さは 6 で、インデックスのリストは 0、1、2 から 5 までです。

画像-76
 >>> string_1 = 'Python'

start値とstop値の両方を指定すると、 startからstop-1までの文字列スライスが得られます。 したがって、 string_1[1:4]は「yth」を返します。

画像-77
 >>> string_1 = 'Python' >>> string_1[1:4] 'yth'

start値を指定しない場合、デフォルトのstart値 0 が使用され、スライスはインデックス 0 から始まり、 stop - 1まで拡張されます。

画像-78

ここでは、 stop値が 3 であるため、スライスはインデックス 0 から始まり、インデックス 2 まで上がります。

 >>> string_1[:3] 'Pyt'

stopインデックスを含めない場合、スライスはstartインデックス (1) から始まり、文字列の最後まで伸びていることがわかります。

画像-80
 >>> string_1[1:] 'ython'

start値とstop値の両方を無視すると、文字列全体のスライスが返されます。

画像-81
 >>> string_1[::] 'Python'

step値でスライスを作成しましょう。 startstop 、およびstepの値をそれぞれ 1、5、および 2 に設定します。 1 から始まり 4 まで (終点 5 を除く) までの文字列のスライスを取得します (終点 5 を除く)。

画像-82
 >>> string_1[1:5:2] 'yh'

負のステップを使用すると、文字列の最後から始まるスライスを取得できます。 ステップを -2 に設定すると、 string_1[5:2:-2]は次のスライスになります。

画像-83
 >>> string_1[5:2:-2] 'nh'

したがって、文字列の逆コピーを取得するには、次のように、 start値と終了値をスキップし、ステップを -1 に設定しstop

 >>> string_1[::-1] 'nohtyP'

要約すると、 string[::-1]は、文字列の逆コピーを返します。

組み込み関数と文字列メソッドを使用した文字列の反転

Python の組み込みのreversed()関数は、文字列の要素に対して逆方向反復子を返します。

 >>> string_1 = 'Python' >>> reversed(string_1) <reversed object at 0x00BEAF70>

したがって、for ループを使用して逆イテレータをループできます。

 for char in reversed(string_1): print(char)

逆の順序で文字列の要素にアクセスします。

 # Output n o h t y P

次に、構文<sep>.join(reversed(some-string))を使用して逆反復子でjoin()メソッドを呼び出すことができます。

以下のコード スニペットは、区切り文字がそれぞれハイフンと空白である 2 つの例を示しています。

 >>> '-'.join(reversed(string1)) 'nohtyP' >>> ' '.join(reversed(string1)) 'nohty P'

ここでは、セパレーターは必要ありません。 そのため、セパレーターを空の文字列に設定して、文字列の逆コピーを取得します。

 >>> ''.join(reversed(string1)) 'nohtyP'

''.join(reversed(some-string))を使用すると、文字列の逆コピーが返されます。

timeit を使用した実行時間の比較

これまでのところ、Python 文字列を逆にする 2 つの方法を学びました。 しかし、どちらが速いですか? 確認してみましょう。

単純な Python 式の時間を測定した前の例では、 setupコードはありませんでした。 ここでは、Python 文字列を反転しています。 文字列反転操作は number で指定されたnumber実行されますが、 setupコードは、1 回だけ実行される文字列の初期化です。

 >>> import timeit >>> timeit.timeit(stmt = 'string_1[::-1]', setup = "string_1 = 'Python'", number = 100000) 0.04951830000001678 >>> timeit.timeit(stmt = "''.join(reversed(string_1))", setup = "string_1 = 'Python'", number = 100000) 0.12858760000000302

指定された文字列を反転する実行回数が同じ場合、文字列スライスアプローチは、 join()メソッドとreversed()関数を使用するよりも高速です。

timeit を使用した Python 関数のタイミング

タイミング-Python-関数-使用-timeit

このセクションでは、timeit 関数を使用して Python 関数の時間を計る方法を学びましょう。 文字列のリストを指定すると、次の関数hasDigitは、少なくとも 1 つの数字を含む文字列のリストを返します。

 def hasDigit(somelist): str_with_digit = [] for string in somelist: check_char = [char.isdigit() for char in string] if any(check_char): str_with_digit.append(string) return str_with_digit

timeitを使用して、この Python 関数hasDigit()の実行時間を測定します。

最初に、時間を計測するステートメント ( stmt ) を特定しましょう。 文字列のリストを引数として関数hasDigit()を呼び出します。 次に、セットアップコードを定義しましょう。 setupコードがどうあるべきか推測できますか?

関数呼び出しを正常に実行するには、セットアップ コードに以下を含める必要があります。

  • 関数hasDigit()の定義
  • 文字列の引数リストの初期化

以下に示すように、 setup文字列でセットアップ コードを定義しましょう。

 setup = """ def hasDigit(somelist): str_with_digit = [] for string in somelist: check_char = [char.isdigit() for char in string] if any(check_char): str_with_digit.append(string) return str_with_digit thislist=['puffin3','7frost','blue'] """

次に、 timeit関数を使用して、100000 回の実行に対するhasDigit()関数の実行時間を取得できます。

 import timeit timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
 # Output 0.2810094920000097

結論

Python の timeit 関数を使用して、式、関数、およびその他の呼び出し可能オブジェクトの時間を計測する方法を学習しました。 これは、コードのベンチマークを行ったり、同じ関数の異なる実装の実行時間を比較したりするのに役立ちます。

このチュートリアルで学んだことを復習しましょう。 timeit()関数は、構文timeit.timeit(stmt=...,setup=...,number=...)使用できます。 または、コマンド ラインで timeit を実行して、短いコード スニペットの時間を計ることもできます。

次のステップとして、line-profiler や memprofiler などの他の Python プロファイリング パッケージを使用して、時間とメモリのそれぞれについてコードをプロファイリングする方法を調べることができます。

次に、Python で時差を計算する方法を学びます。