2010-08-20 19 views
11

Bir if ifadesi kullanıp kullanmama ve birden çok ifade kullanılıyorsa verimlilik arasında fark var mıdır? Başka bir deyişle, daha sonra bir verimlilik açısından farklıPython verimi vs vs multiple ifs

if expr1 == expr2 and expr3==expr4: 
    dostuff() 

gibi bir şey:

if expr1 == expr2: 
    if expr3 == expr4: 
    dostuff() 

Benim çok temel test bir fark ortaya koymamaktadır, ancak daha fazla bilgi (veya daha kapsamlı, en az olan biri yapar test) kesin bir cevap var mı?

+1

http://stackoverflow.com/questions/2539116/python-if-statement-efficiency ilgili olabilir. – anijhaw

+1

Verimlilikle ilgili herhangi bir farklılık bilmiyorum, ancak daha önemli olan, kodunuzun okunabilirliği. Birden çok iç içe geçmiş "if" ifadeleri kullanmak daha netse, mantıklı olduğunu düşündüğünüz şeyi yapın. – derekerdmann

+1

Eğer gerçekten ne olduğunu bilmek istiyorsanız, bunu çözücüde görmelisiniz, fakat ilk ifade, aynı derecede hızlıdır (potansiyel olarak daha hızlıdır, ancak muhtemelen bu şekilde optimize edilmemiştir) çünkü Python kısa devre değerlendirmesi kullanır. –

cevap

4

Her iki durumda da expr1 == expr2, if'da false olarak değerlendirir, ikincisi değerlendirilmez.

14

Bu, kararınızı etkilemek için yeterli bir performans farkına sahip değildir. IMO, buradaki karar sadece okunabilirlik açısından yapılmalıdır. Birincisi genel olarak daha standarttır, ama sanırım ikinci durum daha net olabilir. Niyetinizi en iyi karşılayan yöntemi seçin.

+1

s/IMO //. Performans nedenlerinden ötekilerinden birini ** hemen hemen ** herhangi bir dilde seçmek kesinlikle delilik. Hangisinin daha hızlı olacağını ölçmenin bir yolu yoktur, uygulama istediğini yapabilir. –

+1

Teşekkürler.Genel olarak, katılıyorum ve verimlilik konusunda okunabilirliğe odaklanıyorum. Ancak bu özel durumda, eğer bir döngüde çok sayıda kez çalıştırılıyorsa ve çalışma zamanını azaltma gereği duyuyorum, en azından bu sefer önemli olabilir. – TimothyAWiseman

2

birincisi (and ile bir if) Ben timeit kullanarak bunu denedik hızlı

:-) olduğunu. Son iki için

Variant 1: 9.82836714316 
Variant 2: 9.83886494559 
Variant 1 (True): 9.66493159804 
Variant 2 (True): 10.0392633241 

, ikincisi atlanır bu yüzden ilk karşılaştırılması, True geçerli: Bunlar sonuçlarıdır. İlginç sonuçlar.


import timeit 


print "Variant 1: %s" % timeit.timeit(""" 
for i in xrange(1000): 
    if i == 2*i and i == 3*i: 
     pass 
     """, 
     number = 1000) 

print "Variant 2: %s" % timeit.timeit(""" 
for i in xrange(1000): 
    if i == 2*i: 
     if i == 3*i: 
      pass 
     """, 
     number = 1000) 

print "Variant 1 (True): %s" % timeit.timeit(""" 
for i in xrange(1000): 
    if i == i and i == 3*i: 
     pass 
     """, 
     number = 1000) 

print "Variant 2 (True): %s" % timeit.timeit(""" 
for i in xrange(1000): 
    if i == i: 
     if i == 3*i: 
      pass 
     """, 
     number = 1000) 
10

and kullanarak ve iç içe IFS az olacak arasındaki hız Herhangi farklılıklar. Yanlış ağacı havlıyorsun. Bu ağacı düşünün:

ilk şart ilk değerlendirilmesi gereken sürece

if rarelyTrueCondition and oftenTrueCondition: 

Yani, (o çökmesini veya saçma bir şey/pahalı yapmaktan sonraki ifadeyi durdurmak için bir bekçi) ile karşılaştırıldığında

if oftenTrueCondition and rarelyTrueCondition: 

, Değerlendirme sırasını değiştirmeyi düşünün.

+0

Bunu düşünmediğim ve aslında sayısal işlerde işe yaramayacağımı düşünmek için çok kullanışlı bir yol. Teşekkürler! –

3

Şüphe, sen dis modülü kullanılarak, piton ifadelerinizi derliyor neyi kontrol edebilirsiniz: piton baytkodu düzeyinde, gördüğünüz gibi Yani

>>> import dis 
>>> def test1(): 
...  if expr1 == expr2 and expr3==expr4: 
...  dostuff() 
... 
>>> def test2(): 
...  if expr1 == expr2: 
...  if expr3 == expr4: 
...   dostuff() 
... 
>>> dis.dis(test1) 
    2   0 LOAD_GLOBAL    0 (expr1) 
       3 LOAD_GLOBAL    1 (expr2) 
       6 COMPARE_OP    2 (==) 
       9 JUMP_IF_FALSE   24 (to 36) 
      12 POP_TOP    
      13 LOAD_GLOBAL    2 (expr3) 
      16 LOAD_GLOBAL    3 (expr4) 
      19 COMPARE_OP    2 (==) 
      22 JUMP_IF_FALSE   11 (to 36) 
      25 POP_TOP    

    3   26 LOAD_GLOBAL    4 (dostuff) 
      29 CALL_FUNCTION   0 
      32 POP_TOP    
      33 JUMP_FORWARD    1 (to 37) 
     >> 36 POP_TOP    
     >> 37 LOAD_CONST    0 (None) 
      40 RETURN_VALUE   
>>> dis.dis(test2) 
    2   0 LOAD_GLOBAL    0 (expr1) 
       3 LOAD_GLOBAL    1 (expr2) 
       6 COMPARE_OP    2 (==) 
       9 JUMP_IF_FALSE   28 (to 40) 
      12 POP_TOP    

    3   13 LOAD_GLOBAL    2 (expr3) 
      16 LOAD_GLOBAL    3 (expr4) 
      19 COMPARE_OP    2 (==) 
      22 JUMP_IF_FALSE   11 (to 36) 
      25 POP_TOP    

    4   26 LOAD_GLOBAL    4 (dostuff) 
      29 CALL_FUNCTION   0 
      32 POP_TOP    
      33 JUMP_ABSOLUTE   41 
     >> 36 POP_TOP    
      37 JUMP_FORWARD    1 (to 41) 
     >> 40 POP_TOP    
     >> 41 LOAD_CONST    0 (None) 
      44 RETURN_VALUE   

, hem ifadeler aynıdır - Kullanmak bile ilk ifadede tekse, ilk karşılaştırmadan sonra JUMP_IF_FALSE yapar.