89

python 2.6Python コード (まで3.2) のプロファイリング中strに、オブジェクト (私の場合は整数) を文字列に変換する方法は、文字列の書式設定を使用するよりもほぼ 1 桁遅いことがわかりました。

ベンチマークはこちら

>>> from timeit import Timer
>>> Timer('str(100000)').timeit()
0.3145311339386332
>>> Timer('"%s"%100000').timeit()
0.03803517023435887

なぜこれが事実なのか誰にも分かりますか?何か不足していますか?

4

2 に答える 2

108

'%s' % 100000コンパイラによって評価され、実行時の定数と同等です。

>>> import dis
>>> dis.dis(lambda: str(100000))
  8           0 LOAD_GLOBAL              0 (str)
              3 LOAD_CONST               1 (100000)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda: '%s' % 100000)
  9           0 LOAD_CONST               3 ('100000')
              3 RETURN_VALUE        

%実行時式を使用すると、(大幅に)高速ではありませんstr

>>> Timer('str(x)', 'x=100').timeit()
0.25641703605651855
>>> Timer('"%s" % x', 'x=100').timeit()
0.2169809341430664

@DietrichEppが言ったように、それでも少し遅いことに注意してくださいstr。これは、単一の即時バイトコードにコンパイルするstrときに、ルックアップと関数呼び出しの操作が含まれるためです。%

>>> dis.dis(lambda x: str(x))
  9           0 LOAD_GLOBAL              0 (str)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda x: '%s' % x)
 10           0 LOAD_CONST               1 ('%s')
              3 LOAD_FAST                0 (x)
              6 BINARY_MODULO       
              7 RETURN_VALUE        

もちろん、上記は私がテストしたシステム(CPython 2.7)にも当てはまります。他の実装は異なる場合があります。

于 2012-05-10T08:43:28.690 に答える
15

頭に浮かぶ理由の 1 つstr(100000)は、グローバル ルックアップが含まれるが含まれ"%s"%100000ないという事実です。グローバルは、strグローバル スコープで検索する必要があります。これは違い全体を説明するものではありません。

>>> Timer('str(100000)').timeit()
0.2941889762878418
>>> Timer('x(100000)', 'x=str').timeit()
0.24904918670654297

thg435で指摘されているように、

>>> Timer('"%s"%100000',).timeit()
0.034214019775390625
>>> Timer('"%s"%x','x=100000').timeit()
0.2940788269042969
于 2012-05-10T08:41:42.593 に答える