2010-08-20 12 views
11

Existe-t-il une différence d'efficacité entre l'utilisation et dans une instruction if et l'utilisation de plusieurs instructions if? Autrement dit, est quelque chose commeEfficacité Python de et vs ifs multiples

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

différent d'un point de vue de l'efficacité alors:

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

Mon test très basique ne révèle pas de différence, mais que quelqu'un avec plus de connaissances (ou au moins plus approfondie test) ont une réponse définitive?

+1

http://stackoverflow.com/questions/2539116/python-if-statement-efficiency peut être lié. – anijhaw

+1

Je ne connais pas de différences avec l'efficacité, mais ce qui devrait être plus important est la lisibilité de votre code. S'il est plus clair d'utiliser plusieurs instructions 'if' imbriquées, faites ce que vous pensez logique. – derekerdmann

+1

Vous devriez regarder cela dans le désassembleur si vous voulez vraiment savoir ce qui se passe, mais la première expression est tout aussi rapide (potentiellement plus rapide, mais probablement pas optimisée de cette façon) car Python utilise l'évaluation de court-circuit. –

Répondre

4

Dans les deux cas, expr1 == expr2 évalue à false dans if, le second ne sera pas évalué.

14

Il ne suffit pas d'une différence de performance, le cas échéant, pour affecter votre décision. OMI, la décision ici devrait être faite uniquement dans une perspective de lisibilité. Le premier est généralement plus standard, je pense, mais il y a des situations où la seconde pourrait être plus claire. Choisissez la méthode qui vous convient le mieux.

+1

s/IMO //. Il est absolument insensé de choisir l'un d'entre eux plutôt que l'autre pour des raisons de performance, dans presque tous les langages. Il n'y a aucun moyen de quantifier ce qui sera le plus rapide, l'implémentation peut faire ce qu'elle veut. –

+1

Merci.En général, je suis d'accord et je me concentre sur la lisibilité plutôt que sur l'efficacité. Mais dans ce cas particulier, le si est dans une boucle en cours d'exécution un nombre important de fois et j'ai une exigence pour réduire le temps d'exécution donc, au moins cette fois, cela pourrait avoir de l'importance. – TimothyAWiseman

2

Le premier (un if avec and) est plus rapide :-)

Je l'ai essayé à l'aide timeit. Ce sont les résultats:

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

Pour les deux derniers, la première est True comparision, de sorte que le second est sauté. Des résultats intéressants.


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

Toute différence de vitesse entre l'utilisation and et ifs imbriquées seront minimes. Vous aboyez sur le mauvais arbre. Considérez cet arbre:

if oftenTrueCondition and rarelyTrueCondition: 

par rapport à

if rarelyTrueCondition and oftenTrueCondition: 

Donc, à moins que la première condition doit être évaluée en premier (il est un gardien d'arrêter la prochaine expression de planter ou faire quelque chose de stupide/cher), envisager d'échanger l'ordre d'évaluation.

+0

Un moyen très utile de penser à ce sujet que je n'avais pas pris en compte, et qui sera réellement utile dans le travail numérique. Merci! –

3

En cas de doute, vous pouvez vérifier ce qui ne python compiler vos déclarations, en utilisant dis le module:

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

Comme vous pouvez le voir, au niveau de bytecode python, les deux déclarations sont les mêmes - même si vous utilisez single si à la première déclaration, il fera JUMP_IF_FALSE après la première comparaison.