timeit
文字列の代わりに関数を渡すと、この問題を完全に回避できます。その場合、関数は通常のグローバルおよびクロージャー環境で実行されます。そう:
timeit.timeit(lambda: function(x))
または、必要に応じて:
timeit.timeit(partial(function, x))
(詳細はこちらをご覧ください。Python 2.6+ が必要なので、2.3-2.5 が必要な場合は、このトリックを使用できないことに注意してください。)
ドキュメントにあるように、「この場合、余分な関数呼び出しのため、タイミングのオーバーヘッドが少し大きくなることに注意してください。」
これは、それtimeit
自体の実行が遅くなることを意味します。例えば:
>>> def f(): pass
>>> timeit.timeit('timeit.timeit("f()", setup="from __main__ import f")', setup='import timeit', number=1000)
91.66315175301861
>>> timeit.timeit(lambda: timeit.timeit(f), number=100)
94.89793294097762
ただし、実際の結果には影響しません。
>>> timeit.timeit(f, number=100000000)
8.81197881908156
>>> timeit.timeit('f()', setup='from __main__ import f', number=100000000)
8.893913001054898
(まれなケースですが、これは通常、どちらかのバージョンが実際のコードで呼び出される方法で関数をテストしていなかったか、間違ったクロージャなどをテストしていたことを意味します。)
ここで関数内で実際にかかった時間は約 88 秒であるため、タイミング コードのオーバーヘッドはほぼ 2 倍になりましたが、合計テスト時間の 3% しか追加されていません。そして、些細でないf
ほど、この差は小さくなります。