为什么repr(int)比str(int)更快?

Chr*_*ier 34 python performance python-internals

我想知道为什么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()
Run Code Online (Sandbox Code Playgroud)

我得到了这些时间(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)
Run Code Online (Sandbox Code Playgroud)

如果我走在正确的道路上,同样的功能long_to_decimal_string就会在引擎盖下面调用.

我错了什么或者我还缺少什么?


更新:这可能没有什么用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()
Run Code Online (Sandbox Code Playgroud)

结果是:

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)
Run Code Online (Sandbox Code Playgroud)

Jim*_*ard 33

因为str(obj)必须首先通过type.__call__然后str.__new__(创建一个新的字符串)然后PyObject_Str(从对象中创建一个字符串)调用int.__str__,最后使用你链接的函数.

repr(obj),对应于builtin_repr,直接调用PyObject_Repr(获取对象repr)然后调用int.__repr__它使用相同的函数int.__str__.

此外,它们所采用的路径call_function(处理为调用生成的CALL_FUNCTION操作码的函数)略有不同.

来自GitHub上的主分支(CPython 3.7):

正如你的更新所述,这不是关于int.__repr__vs int.__str__,它们毕竟是相同的功能; 它是关于如何reprstr达到它们的全部.str只需要更努力地工作.


ari*_*tll 12

我只是比较了3.5分支中的strrepr实现.看到这里.

似乎有更多的检查str:在此输入图像描述


MSe*_*ert 8

有几种可能性,因为负责strrepr返回的CPython函数略有不同.

但我想主要的原因是,strtype(A类)和str.__new__方法调用__str__,同时repr可以直接去__repr__.