6

Python で timeit モジュール (編集: Python 3 を使用しています) を使用して、いくつかの異なるコード フローを決定しようとしています。このコードには、文字列内に文字コードが存在するかどうかをテストする一連の if ステートメントがあり、存在する場合は次のように置き換えます。

if "<substring>" in str_var:
    str_var = str_var.replace("<substring>", "<new_substring>")

これをさまざまな部分文字列に対して何度も行います。それと、次のような置換のみを使用することとの間で議論しています。

str_var = str_var.replace("<substring>", "<new_substring>")

timeit を使用して、どちらが高速かを判断しようとしました。上記の最初のコード ブロックが「stmt1」で 2 番目が「stmt2」の場合、セットアップ文字列は次のようになります。

str_var = '<string><substring><more_string>',

timeit ステートメントは次のようになります。

timeit.timeit(stmt=stmt1, setup=setup)

timeit.timeit(stmt=stmt2, setup=setup)

さて、同じように実行すると、2台のラップトップ(同じハードウェア、同様の処理負荷)でstmt1(ifステートメントを含むステートメント)が複数回実行した後でも高速に実行されます(100分の3〜4秒対約4分の1秒) stmt2 の 1 秒)。

ただし、両方のことを行う関数を定義すると (変数を作成するセットアップを含む)、次のようになります。

def foo():
    str_var = '<string><substring><more_string>'
    if "<substring>" in str_var:
        str_var = str_var.replace("<substring>", "<new_substring>")

def foo2():
    str_var = '<string><substring><more_string>'
    str_var = str_var.replace("<substring>", "<new_substring>")

実行時は次のようになります。

timeit.timeit("foo()", setup="from __main__ import foo")
timeit.timeit("foo2()", setup="from __main__ import foo2")

if ステートメントのないステートメント (foo2) はより高速に実行され、関数化されていない結果と矛盾します。

Timeit の仕組みについて何か不足していますか? または、Python はこのようなケースをどのように処理しますか?

実際のコードは次のとおりです。

>>> def foo():
    s = "hi 1 2 3"
    s = s.replace('1','5')

>>> def foo2():
    s = "hi 1 2 3"
    if '1' in s:
        s = s.replace('1','5')


>>> timeit.timeit(foo, "from __main__ import foo")
0.4094226634183542
>>> timeit.timeit(foo2, "from __main__ import foo2")
0.4815539780738618

対このコード:

>>> timeit.timeit("""s = s.replace("1","5")""", setup="s = 'hi 1 2 3'")
0.18738432400277816
>>> timeit.timeit("""if '1' in s: s = s.replace('1','5')""", setup="s = 'hi 1 2 3'")
0.02985000199987553
4

2 に答える 2