なぜrepr(int)
がstr(int)
より速いのか疑問に思っています。次のコードスニペットを使用します。
_ROUNDS = 10000
def concat_strings_str():
return ''.join(map(str, range(ROUNDS)))
def concat_strings_repr():
return ''.join(map(repr, range(ROUNDS)))
%timeit concat_strings_str()
%timeit concat_strings_repr()
_
私はこれらのタイミングを取得します(python 3.5.2ですが、2.7.12と非常に似た結果):
_ 1.9 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.38 ms ± 9.07 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
_
私が正しい道を進んでいる場合、内部では 同じ関数_long_to_decimal_string
_が呼び出されます です。
私は何か間違ったことをしたのですか、それとも他に何が起こっているのですか?
update:これはおそらくint
の___repr__
_または___str__
_メソッドとは関係ありませんが、repr()
とstr()
は、_int.__str__
_と_int.__repr__
_が実際には比較的高速であるためです。
_def concat_strings_str():
return ''.join([one.__str__() for one in range(ROUNDS)])
def concat_strings_repr():
return ''.join([one.__repr__() for one in range(ROUNDS)])
%timeit concat_strings_str()
%timeit concat_strings_repr()
_
結果は:
_2.02 ms ± 24.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.05 ms ± 7.07 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
_
str(obj)
を使用するには、最初に_type.__call__
_、 _str.__new__
_(新しい文字列を作成) 、 _PyObject_Str
_(オブジェクトから文字列を作成する)_int.__str__
_ を呼び出す、およびfinally、リンクした関数を使用します。
_builtin_repr
_に対応するrepr(obj)
は、 を直接呼び出します_PyObject_Repr
_(オブジェクトのreprを取得) は、 を呼び出します_int.__repr__
_と同じ関数を使用する_int.__str__
_ .
さらに、それらが通るパス _call_function
_ ( _CALL_FUNCTION
_ opcode を処理する関数)は、呼び出し用に生成されます)は少し異なります。
GitHub(CPython 3.7)のマスターブランチから:
str
は __PyObject_FastCallKeywords
_ を通過します(これは_type.__call__
_を呼び出すものです)。より多くのチェックを実行する以外に、これは位置引数を保持するタプルを作成する必要もあります( __PyStack_AsTuple
_ を参照)。repr
は __PyCFunction_FastCallKeywords
_ を経由し、 __PyMethodDef_RawFastCallKeywords
_ を呼び出します。 repr
も幸運です。これは、引数を1つしか受け入れないためです(スイッチが_METH_0
_の__PyMethodDef_RawFastCallKeywords
_の場合を導く)。タプルを作成する必要はなく、 args のインデックス。あなたの更新が述べているように、これは_int.__repr__
_と_int.__str__
_ではなく、結局同じ関数です。 repr
とstr
がそれらに到達する方法がすべてです。 str
はもう少し頑張る必要があります。
3.5ブランチのstr
とrepr
の実装を比較したところです。 こちら を参照してください。
str
と repr
を返すCPython関数はわずかに異なるため、いくつかの可能性があります。
しかし、主な理由は、str
がtype
(クラス)であり、 str.__new__
メソッドが __str__
一方、repr
は__repr__
に直接アクセスできます。