Par exemple, si j'ai la déclaration suivante:
if( foo1 or foo2)
...
...
si foo1 est vrai, python vérifiera-t-il l'état de foo2?
Oui, Python évalue les conditions booléennes paresseusement.
Les les docs disent ,
L'expression x et y évalue d'abord x; si x est faux, sa valeur est retournée; sinon, y est évalué et la valeur résultante est renvoyée.
L'expression x ou y évalue d'abord x; si x est vrai, sa valeur est retournée; sinon, y est évalué et la valeur résultante est renvoyée.
and
or
est paresseux
&
|
n'est pas paresseux
La paresse de Python peut être prouvée par le code suivant:
def foo():
print('foo')
return False
def bar():
print('bar')
return False
foo() and bar() #Only 'foo' is printed
D'autre part,
foo() or bar()
entraînerait à la fois "foo" et "bar" à imprimer.
Ce n'est pas une évaluation techniquement paresseuse, ce sont des expressions booléennes de court-circuit.
L'évaluation paresseuse a une connotation quelque peu différente. Par exemple, une véritable évaluation paresseuse permettrait probablement
def foo(arg) :
print "Couldn't care less"
foo([][0])
Mais Python ne le fait pas.
Python est également agréable en ce qu'il "fait écho" à ses arguments booléens. Par exemple, une condition ou renvoie soit son premier argument "véridique" soit le dernier argument (si tous les arguments sont "falsey"). Une condition et fait l'inverse.
Donc, "l'argument d'écho" booléens signifie
2 et [] et 1
évalue à [], et
[] ou 1 ou 2
évalue à 1
Oui, Python évalue paresseusement, donc foo2
ne sera pas vérifié.
Je l'utilise tout le temps pour récupérer des éléments à partir d'objets de type dictionnaire si je ne sais pas si la clé existe:
if 'key' in mydict and mydict['key'] == 'heyyo!':
do_stuff()
Voir la réponse de @ unutbu pour une explication plus complète.
C'est vraiment la partie or
qui est court-circuitée:
>>> 1 or 1/0 #also 0 and 1/0
1
>>> 0 or 1/0 #also 1 and 1/0
Traceback (most recent call last):
File "<pyshell#1240>", line 1, in <module>
0 or 1/0
ZeroDivisionError: integer division or modulo by zero
Une courte démonstration serait de comparer la différence de temps entre
all(xrange(1,1000000000))
et
any(xrange(1,1000000000))
Le all () doit vérifier chaque valeur unique, tandis que le any () peut abandonner une fois que le premier True a été trouvé. Le xrange, étant un générateur, renonce donc également à générer des choses dès que l'évaluateur a terminé. Pour cette raison, le tout consommera de grandes quantités de RAM et prendra des âges, tandis que le tout n'utilisera que quelques octets et reviendra instantanément.