web-dev-qa-db-ja.com

repr(int)がstr(int)より速いのはなぜですか?

なぜ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)
_
34
Christian Geier

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___ではなく、結局同じ関数です。 reprstrがそれらに到達する方法がすべてです。 strはもう少し頑張る必要があります。

3.5ブランチのstrreprの実装を比較したところです。 こちら を参照してください。

strにはさらにチェックがあるようです: enter image description here

12
aristotll

strrepr を返すCPython関数はわずかに異なるため、いくつかの可能性があります。

しかし、主な理由は、strtype(クラス)であり、 str.__new__ メソッドが __str__ 一方、repr__repr__に直接アクセスできます。

8
MSeifert