11

配列を取り、すべての要素を 0 に変更する関数があるとします。

def function(array):
    for i in range(0,len(array)):
        array[i] = 0
return array

この関数をランダムな配列で実行するのにかかる時間をテストしたいのですが、timeit テストの外側で生成したいと考えています。つまり、配列の生成にかかる時間を時間に含めたくありません。

最初に乱数配列を変数 x に格納し、次のようにします。

timeit.timeit("function(x)",setup="from __main__ import function")

しかし、これは私にエラーを与えます: NameError: グローバル名 'x' は定義されていません

これどうやってするの?

4

5 に答える 5

22

xから__main__ インポート:

timeit.timeit("function(x)", setup="from __main__ import function, x")

と同じようfunctionx、モジュール内の名前であり__main__、セットアップにインポートできtimeitます。

于 2013-09-18T21:36:48.473 に答える
12

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ほど、この差は小さくなります。

于 2013-09-18T21:38:39.503 に答える
3

インポート元x:__main__

timeit.timeit("function(x)",setup="from __main__ import function, x")
于 2013-09-18T21:36:56.130 に答える