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

Python 为什么repr(int)比str(int)快?,python,performance,python-internals,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_re

我想知道为什么
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的结果非常相似):

如果我在正确的道路上,在引擎盖下面

我是不是做错了什么,或者我还错过了什么


更新: 这可能与
int
\uuuu repr\uuuuu
\uu str\uuuuu
方法无关,但与
repr()
str()
之间的差异有关,如
int.\uu str\uuuuuu
int.\uu repr\uuu
实际上速度相当快:

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)

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


但我想主要原因是
str
类型(一个类),方法必须调用,
repr
可以直接转到
\uuuuurepr\uuuuuuu

我刚刚比较了
str
repr
在3.5分支中的实现。 看

str

中似乎有更多的检查,因为使用
str(obj)
必须首先通过
类型。然后调用\uuuuuuu
,然后调用,最后使用链接的函数

repr(obj)
,它对应于
内置repr
,直接调用,然后调用与
int.\uu str\uuu
相同的函数

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

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

  • str
    通过(调用
    type.\uuu调用\uuu
    )。除了执行更多检查外,还需要创建一个元组来保存位置参数(请参阅)
  • repr
    执行哪些调用
    repr
    也很幸运,因为它只接受一个参数(在
    \u PyMethodDef\u RawFastCallKeywords
    中,该开关将其引导到
    METH\u 0
    案例),因此不需要创建元组,只需创建一个元组即可

正如您的更新所述,这与
int.\uu repr\uuu
vs
int.\uu str\uuu
无关,它们毕竟是相同的函数;这都是关于如何
repr
str
达到他们的
str
只需要再努力一点

我在Windows10上安装了Python2.7.13,因为我认为在我的机器上没有明显的区别。您是否尝试过切换顺序并查看是否是某种系统资源影响?@gbtimmon顺序没有区别。我能够使用
python3-m timeit“''.join(map(repr,range(10000))”
和等效的
str
版本或多次运行在OS X上可靠地复制。这应该可以消除对缓存等的大部分担忧。但是如果我去掉
连接
,差异就会消失
python3-m timeit“map(str,range(10000))”
@RobNapier不使用
join
repr
(或
str
)实际上不会被调用。@python3
map
中的RobNapier返回一个迭代器,因此实际上不会执行任何操作-您需要构造列表,例如
python3-m timeit”列表(map(str,范围(10000))“
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)