Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

str performance in python

While profiling a piece of python code (python 2.6 up to 3.2), I discovered that the str method to convert an object (in my case an integer) to a string is almost an order of magnitude slower than using string formatting.

Here is the benchmark

>>> from timeit import Timer >>> Timer('str(100000)').timeit() 0.3145311339386332 >>> Timer('"%s"%100000').timeit() 0.03803517023435887 

Does anyone know why this is the case? Am I missing something?

like image 249
Luca Sbardella Avatar asked May 10 '12 08:05

Luca Sbardella


People also ask

What is STR for in Python?

Python str() Function The str() function converts the specified value into a string.

Does str () work on lists?

When you call str(l) , it returns a printable form of the list l , that is "['a','b']" . Thus when you call the list on a string you get a list of character. Note that again here, when you call str() on list('dummy') , you will not get back your original string 'dummy' , so again you will have to use join !

Is str () a method?

The str() method returns the string representation of a given object.

What does STR 1 mean in Python?

It means, "start at the end; count down to the beginning, stepping backwards one step at a time."


1 Answers

'%s' % 100000 is evaluated by the compiler and is equivalent to a constant at run-time.

>>> import dis >>> dis.dis(lambda: str(100000))   8           0 LOAD_GLOBAL              0 (str)               3 LOAD_CONST               1 (100000)               6 CALL_FUNCTION            1               9 RETURN_VALUE         >>> dis.dis(lambda: '%s' % 100000)   9           0 LOAD_CONST               3 ('100000')               3 RETURN_VALUE         

% with a run-time expression is not (significantly) faster than str:

>>> Timer('str(x)', 'x=100').timeit() 0.25641703605651855 >>> Timer('"%s" % x', 'x=100').timeit() 0.2169809341430664 

Do note that str is still slightly slower, as @DietrichEpp said, this is because str involves lookup and function call operations, while % compiles to a single immediate bytecode:

>>> dis.dis(lambda x: str(x))   9           0 LOAD_GLOBAL              0 (str)               3 LOAD_FAST                0 (x)               6 CALL_FUNCTION            1               9 RETURN_VALUE         >>> dis.dis(lambda x: '%s' % x)  10           0 LOAD_CONST               1 ('%s')               3 LOAD_FAST                0 (x)               6 BINARY_MODULO                      7 RETURN_VALUE         

Of course the above is true for the system I tested on (CPython 2.7); other implementations may differ.

like image 109
georg Avatar answered Oct 08 '22 22:10

georg