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 式のタイミング
このセクションでは、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 に設定されます。これは、指定されたnumber
のstmt
の実行が 5 回繰り返され、最良の実行時間が返されることを意味します。
timeit を使用した文字列反転メソッドの分析
Python 文字列を操作する場合、それらを逆にしたい場合があります。 文字列反転の最も一般的な 2 つの方法は次のとおりです。
- 文字列スライスの使用
reversed()
関数とjoin()
メソッドの使用
文字列スライスを使用した Python 文字列の反転
文字列スライスの仕組みと、それを使用して Python 文字列を逆にする方法について説明しましょう。 構文some-string[start:stop]
を使用すると、インデックスstart
からインデックスstop-1
までの文字列のスライスが返されます。 例を見てみましょう。
次の文字列「Python」を考えてみましょう。 文字列の長さは 6 で、インデックスのリストは 0、1、2 から 5 までです。
>>> string_1 = 'Python'
start
値とstop
値の両方を指定すると、 start
からstop-1
までの文字列スライスが得られます。 したがって、 string_1[1:4]
は「yth」を返します。
>>> string_1 = 'Python' >>> string_1[1:4] 'yth'
start
値を指定しない場合、デフォルトのstart
値 0 が使用され、スライスはインデックス 0 から始まり、 stop - 1
まで拡張されます。
ここでは、 stop
値が 3 であるため、スライスはインデックス 0 から始まり、インデックス 2 まで上がります。
>>> string_1[:3] 'Pyt'
stop
インデックスを含めない場合、スライスはstart
インデックス (1) から始まり、文字列の最後まで伸びていることがわかります。
>>> string_1[1:] 'ython'
start
値とstop
値の両方を無視すると、文字列全体のスライスが返されます。
>>> string_1[::] 'Python'
step
値でスライスを作成しましょう。 start
、 stop
、およびstep
の値をそれぞれ 1、5、および 2 に設定します。 1 から始まり 4 まで (終点 5 を除く) までの文字列のスライスを取得します (終点 5 を除く)。
>>> string_1[1:5:2] 'yh'
負のステップを使用すると、文字列の最後から始まるスライスを取得できます。 ステップを -2 に設定すると、 string_1[5:2:-2]
は次のスライスになります。
>>> 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 関数のタイミング
このセクションでは、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 で時差を計算する方法を学びます。