str performance in python


88

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?


2
Dan bagaimana dengan'{}'.format(100000)
— wim

Itu yang paling lambat tapi juga paling fleksibel.
— Luca Sbardella

Jawaban:


106

'%s' % 100000 dievaluasi oleh kompilator dan setara dengan konstanta pada waktu proses.

>>> 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        

% dengan ekspresi run-time tidak (secara signifikan) lebih cepat dari str :

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

Perhatikan bahwa strmasih sedikit lebih lambat, seperti yang dikatakan @DietrichEpp, ini karenastr melibatkan operasi pencarian dan pemanggilan fungsi, sementara %mengkompilasi ke satu bytecode langsung:

>>> 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        

Tentu saja hal di atas berlaku untuk sistem yang saya uji (CPython 2.7); implementasi lain mungkin berbeda.


Indeed this looks like the reason, I just tried myself and string formatting is just about 5% faster than str. Thanks for answer. No reason to change code everywhere :-)
— Luca Sbardella

2
To elaborate further: str is a name that can be rebound to something other than the string type, but string formatting - i.e. the str.__mod__ method - cannot be replaced, which permits the compiler to do the optimization. The compiler doesn't do very much in the way of optimization, but it does more than you might think :)
— Karl Knechtel

4
... dan pelajaran yang bisa dipelajari di sini adalah: jangan pernah menggunakan literal dalam tes seperti ini!
— UncleZeiv

Entri blog khusus ini mungkin menarik bagi Anda: skymind.com/~ocrow/python_string . Ini berisi bagan tolok ukur untuk berbagai metode penggabungan string yang serupa dengan yang Anda berikan di atas.
— Aaron Newton

14

Salah satu alasan yang terlintas dalam pikiran adalah fakta yang str(100000)melibatkan pencarian global, tetapi "%s"%100000tidak. The strglobal yang harus mendongak dalam lingkup global. Ini tidak memperhitungkan seluruh perbedaan:

>>> Timer('str(100000)').timeit()
0.2941889762878418
>>> Timer('x(100000)', 'x=str').timeit()
0.24904918670654297

Seperti dicatat oleh thg435 ,

>>> Timer('"%s"%100000',).timeit()
0.034214019775390625
>>> Timer('"%s"%x','x=100000').timeit()
0.2940788269042969
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.