python'da str performansı


88

Bir python kodunun profilini çıkarırken ( python 2.6en fazla 3.2), strbir nesneyi (benim durumumda bir tamsayı) bir dizeye dönüştürme yönteminin, dize biçimlendirmesini kullanmaktan neredeyse bir büyüklük sırası daha yavaş olduğunu keşfettim .

İşte kriter

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

Bunun neden böyle olduğunu bilen var mı? Bir şey mi kaçırıyorum?


2
Peki ya'{}'.format(100000)
wim

Bu en yavaş ama aynı zamanda en esnek olanıdır.
Luca Sbardella

Yanıtlar:


106

'%s' % 100000 derleyici tarafından değerlendirilir ve çalışma zamanında bir sabite eşdeğerdir.

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

%çalışma zamanı ifadesi şunlardan (önemli ölçüde) daha hızlı değildir str:

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

str@DietrichEpp'in dediği gibi bunun hala biraz daha yavaş olduğunu unutmayın , bunun nedeni strarama ve işlev çağrısı işlemlerini içerirken, %tek bir anlık bayt koduna derlenir:

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

Tabii ki yukarıda test ettiğim sistem (CPython 2.7) için de geçerlidir; diğer uygulamalar farklılık gösterebilir.


Aslında bunun sebebi bu gibi görünüyor, ben kendim denedim ve dize biçimlendirmesinden yaklaşık% 5 daha hızlı str. Cevap için teşekkürler. Her yerde kodu değiştirmek için bir neden yok :-)
Luca Sbardella

2
Daha fazla detaylandırmak gerekirse: strdize türü dışında bir şeye geri dönebilen bir addır, ancak dize biçimlendirmesi - yani str.__mod__yöntem - değiştirilemez, bu da derleyicinin optimizasyonu yapmasına izin verir. Derleyici optimizasyon yolunda pek bir şey yapmaz, ancak düşündüğünüzden fazlasını yapar :)
Karl Knechtel

4
... ve buradan öğrenilecek ders şudur: böyle testlerde asla değişmez değerleri kullanmayın!
UncleZeiv

Bu belirli blog girişi ilginizi çekebilir: skymind.com/~ocrow/python_string . Yukarıda sağladıklarınıza benzer çeşitli dizi birleştirme yöntemleri için bir kıyaslama çizelgesi içerir.
Aaron Newton

14

Akla gelen nedenlerden biri str(100000), küresel bir arama içeren, ancak "%s"%100000içermeyen gerçektir . strKüresel küresel kapsamda baktım gerekmektedir. Bu, tüm farkı hesaba katmaz:

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

Thg435 tarafından belirtildiği gibi ,

>>> Timer('"%s"%100000',).timeit()
0.034214019775390625
>>> Timer('"%s"%x','x=100000').timeit()
0.2940788269042969
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.