I am wondering why repr(int)
is faster than str(int)
. With the following code snippet:
ROUNDS = 10000
def concat_strings_str():
re
Because using str(obj)
must first go through type.__call__
then str.__new__ (create a new string) then PyObject_Str (make a string out of the object) which invokes int.__str__ and, finally, uses the function you linked.
repr(obj)
, which corresponds to builtin_repr
, directly calls PyObject_Repr (get the object repr) which then calls int.__repr__ which uses the same function as int.__str__
.
Additionally, the path they take through call_function (the function that handles the CALL_FUNCTION opcode that's generated for calls) is slightly different.
From the master branch on GitHub (CPython 3.7):
str
goes through _PyObject_FastCallKeywords (which is the one that calls type.__call__
). Apart from performing more checks, this also needs to create a tuple to hold the positional arguments (see _PyStack_AsTuple). repr
goes through _PyCFunction_FastCallKeywords which calls _PyMethodDef_RawFastCallKeywords. repr
is also lucky because, since it only accepts a single argument (the switch leads it to the METH_0
case in _PyMethodDef_RawFastCallKeywords
) there's no need to create a tuple, just indexing of the args. As your update states, this isn't about int.__repr__
vs int.__str__
, they are the same function after all; it's all about how repr
and str
reach them. str
just needs to work a bit harder.
There are several possibilities because the CPython functions that are responsible for the str and repr return are slightly different.
But I guess the primary reason is that str
is a type
(a class) and the str.__new__ method has to call __str__ while repr
can directly go to __repr__
.
I just compared the str
and repr
implementations in the 3.5 branch.
See here.
There seems to be more checks in str
: