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

Why is repr(int) faster than 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)

如果我在正确的道路上,the same function long_to_decimal_string is getting called 幕后。

我是不是弄错了什么或者我还遗漏了什么?


更新: 这可能与 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 and repr return 的 CPython 函数略有不同。

但我猜主要原因是str是一个type(一个class)而str.__new__ method has to call __str__repr可以直接去__repr__.

我刚刚比较了 3.5 分支中的 strrepr 实现。 参见 here

str中似乎有更多检查:

因为使用 str(obj) 必须首先经过 type.__call__ 然后 str.__new__ (create a new string) then PyObject_Str (make a string out of the object) which invokes int.__str__ 并且 最后 使用您链接的函数。

repr(obj),对应builtin_repr,直接调用PyObject_Repr (get the object repr) which then calls int.__repr__,与int.__str__.

使用相同的功能

此外,他们通过 call_function (the function that handles the CALL_FUNCTION opcode 为调用生成的路径)略有 不同。

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

如您的更新所述,这与 int.__repr__int.__str__ 无关,毕竟它们是相同的功能;这完全是关于 reprstr 如何到达他们。 str只是需要再努力一点。