web-dev-qa-db-ja.com

関数に変数を渡すときにpython timeitを使用するには?

私はtimeitを使用してこれに苦労しており、誰かがヒントを持っているかどうか疑問に思っていました

基本的に、速度をテストして作成した関数(値を渡す関数)があります。

if __name__=='__main__':
    from timeit import Timer
    t = Timer(superMegaIntenseFunction(10))
    print t.timeit(number=1)

しかし、実行すると、timeitモジュールからのような奇妙なエラーが発生します。

ValueError: stmt is neither a string nor callable

関数を単独で実行すると、正常に機能します。そのモジュールにラップすると、エラーが発生します(二重引用符を使用して、.. sameoutputなしで試しました)。

どんな提案でも素晴らしいでしょう!

ありがとう!

72
Lostsoul

それを呼び出し可能にします:

if __name__=='__main__':
    from timeit import Timer
    t = Timer(lambda: superMegaIntenseFunction(10))
    print(t.timeit(number=1))

動作するはずです

116
Pablo

Timer(superMegaIntenseFunction(10))は、「superMegaIntenseFunction(10)を呼び出し、その結果をTimerに渡す」ことを意味します。それは明らかにあなたが望むものではありません。 Timerは、呼び出し可能なもの(聞こえるとおり:関数など、呼び出すことができるもの)または文字列(文字列の内容をPython code)。Timerはcallable-thingを繰り返し呼び出して、どれだけ時間がかかっているかを確認することで機能します。

superMegaIntenseFunctionは呼び出し可能なため、Timer(superMegaIntenseFunction)は型チェックに合格します。ただし、TimersuperMegaIntenseFunctionに渡す値を知りません。

もちろん、これを回避する簡単な方法は、コードで文字列を使用することです。文字列は新しいコンテキストで「コードとして解釈される」ため、「setup」引数をコードに渡す必要があります。同じglobalsにアクセスできないため、別のビットを実行する必要があります定義を利用可能にするコードの詳細-@oxtopusの回答を参照してください。

lambda(@Pabloの答えのように)を使用すると、パラメーター10superMegaIntenseFunctionの呼び出しにバインドできます。私たちがしていることは、引数を取らず、10superMegaIntenseFunctionを呼び出す別の関数を作成することだけです。 defを使用してそのような別の関数を作成した場合と同じです。ただし、新しい関数は名前を取得しません(名前が必要ないため)。

23
Karl Knechtel

文字列を渡す必要があります。つまり.

t = Timer('superMegaIntenseFunction(10)','from __main__ import superMegaIntenseFunction')
18
Austin Marshall

将来の訪問者へのメモ。 pdbデバッガーで動作させる必要があり、superMegaIntenseFunctionがグローバルスコープにない場合は、globalsに追加して動作させることができます。

globals()['superMegaIntenseFunction'] = superMegaIntenseFunction
timeit.timeit(lambda: superMegaIntenseFunction(x))

この場合、余分な関数呼び出しのために、タイミングのオーバーヘッドが少し大きくなることに注意してください。 [ソース]

1

これを行う1つの方法は、パーシャルを使用して、関数 'superMegaIntenseFunction'を呼び出し可能として(つまり()なしで)タイマーで、またはtimeit.timeitの内部で直接使用することです。 partialを使用すると、タイマーによって呼び出されるときに関数に引数が渡されます。

from functools import partial
from timeit import timeit

print(timeit(partial(superMegaIntenseFunction, 10), number=1))
0
Coding Paradigm