web-dev-qa-db-fra.com

Est-ce que Python prend en charge les courts-circuits?

Est-ce que Python prend en charge les courts-circuits dans les expressions booléennes?

292
Dinah

Oui, les deux opérateurs and et or court-circuitent - voir la documentation .

274
Alex Martelli

Comportement de court-circuit dans l'opérateur and, or:

Définissons d'abord une fonction utile pour déterminer si quelque chose est exécuté ou non. Une fonction simple qui accepte un argument, imprime un message et renvoie l'entrée sous forme inchangée.

>>> def fun(i):
...     print "executed"
...     return i
... 

On peut observer les opérateurs comportement de court-circuitage de Python des opérateurs and, or dans l'exemple suivant:

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

Remarque: L'interpréteur considère que les valeurs suivantes sont fausses:

        False    None    0    ""    ()    []     {}

Comportement de court-circuit dans la fonction: any(), all():

Les fonctions any() et all() de= (__) supportent également les court-circuits. Comme indiqué dans la documentation; ils évaluent chaque élément d'une séquence dans l'ordre, jusqu'à trouver un résultat permettant une sortie rapide de l'évaluation. Considérez les exemples ci-dessous pour comprendre les deux.

La fonction any() vérifie si l'un des éléments est True. Il cesse de s'exécuter dès qu'un True est rencontré et renvoie True.

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

La fonction all() vérifie que tous les éléments sont vrais et arrête de s’exécuter dès qu’un faux est rencontré:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

Comportement de court-circuit dans la comparaison chaînée:

De plus, en Python

Les comparaisons peuvent être chaînées arbitrairement ; Par exemple, x < y <= z est équivalent à x < y and y <= z, sauf que y est évalué une seule fois (mais dans les deux cas, z n'est pas du tout évalué lorsque x < y est trouvé faux).

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

Modifier:
Un autre point intéressant à noter : - Logique and, or opérateurs dans Python renvoie un opérande valeur au lieu d'un booléen (True ou False). Par exemple:

L'opération x and y donne le résultat if x is false, then x, else y

Contrairement à d'autres langues, par exemple &&, || opérateurs en C renvoyant 0 ou 1.

Exemples:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

De même, l'opérateur or renvoie la valeur la plus à gauche pour laquelle bool(value) == True la valeur la plus fausse à droite (selon le comportement de court-circuit), exemples:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

Alors, comment est-ce utile? Un exemple d'utilisation donné dans Practical Python Par Magnus Lie Hetland:
Supposons qu’un utilisateur est censé entrer son nom mais peut choisir de ne rien entrer, auquel cas vous souhaitez utiliser la valeur par défaut '<unknown>'. Vous pouvez utiliser une instruction if, mais vous pouvez également énoncer les choses très succinctement:

In [171]: name = raw_input('Enter Name: ') or '<Unkown>'
Enter Name: 

In [172]: name
Out[172]: '<Unkown>'

En d'autres termes, si la valeur renvoyée par raw_input est true (pas une chaîne vide), elle est assignée à name (rien ne change); sinon, le '<unknown>' par défaut est attribué à name.

174
Grijesh Chauhan

Oui. Essayez ce qui suit dans votre interprète python:

et

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

ou

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
46
Caprooja