TL; DR
Nous commençons par résumer les deux comportements des deux opérateurs logiques and
et or
. Ces expressions idiomatiques formeront la base de notre discussion ci-dessous.
and
Renvoie la première valeur Falsy s'il y en a, sinon renvoie la dernière valeur de l'expression.
or
Renvoie la première valeur Truthy s'il y en a, sinon renvoie la dernière valeur de l'expression.
Le comportement est également résumé dans la documentation , en particulier dans ce tableau:
Le seul opérateur renvoyant une valeur booléenne indépendamment de ses opérandes est l' not
opérateur.
Évaluations "Vérité" et "Vérité"
La déclaration
len(args) and max(args) - min(args)
Est une manière très pythonique concise (et sans doute moins lisible) de dire "si ce args
n'est pas vide, renvoie le résultat de max(args) - min(args)
", sinon retourne 0
. En général, il s'agit d'une représentation plus concise d'une if-else
expression. Par exemple,
exp1 and exp2
Devrait (à peu près) se traduire par:
r1 = exp1
if r1:
r1 = exp2
Ou équivalent,
r1 = exp1 if exp1 else exp2
De même,
exp1 or exp2
Est équivalent à,
r1 = exp1
if not r1:
r1 = exp2
Où exp1
et exp2
sont des objets Python arbitraires ou des expressions qui renvoient un objet. La clé pour comprendre les utilisations des opérateurs logiques and
et or
ici est de comprendre qu'ils ne se limitent pas à fonctionner ou à renvoyer des valeurs booléennes. Tout objet avec une valeur de vérité peut être testé ici. Cela inclut int
, str
, list
, dict
, tuple
, set
, NoneType
et objets définis par l' utilisateur. Les règles de court-circuit s'appliquent également.
Mais qu'est-ce que la vérité?
Il fait référence à la manière dont les objets sont évalués lorsqu'ils sont utilisés dans des expressions conditionnelles. @Patrick Haugh résume bien la vérité dans cet article .
Toutes les valeurs sont considérées comme "véridiques", à l'exception des suivantes, qui sont "fausses":
None
False
0
0.0
0j
Decimal(0)
Fraction(0, 1)
[]
- un vide list
{}
- un vide dict
()
- un vide tuple
''
- un vide str
b''
- un vide bytes
set()
- un vide set
- un vide
range
, commerange(0)
- objets pour lesquels
obj.__bool__()
Retour False
obj.__len__()
Retour 0
Une valeur "véridique" satisfera le contrôle effectué par les
instructions if
ou while
. Nous utilisons «véridique» et «faux» pour différencier les
bool
valeurs True
et False
.
Comment and
fonctionne
Nous nous appuyons sur la question d'OP comme une suite dans une discussion sur la façon dont ces opérateurs dans ces cas.
Étant donné une fonction avec la définition
def foo(*args):
...
Comment renvoyer la différence entre la valeur minimale et la valeur maximale dans une liste de zéro ou plusieurs arguments?
Trouver le minimum et le maximum est facile (utilisez les fonctions intégrées!). Le seul hic ici est de gérer correctement le cas du coin où la liste d'arguments pourrait être vide (par exemple, appeler foo()
). Nous pouvons faire les deux en une seule ligne grâce à l' and
opérateur:
def foo(*args):
return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5)
# 4
foo()
# 0
Depuis and
est utilisé, la deuxième expression doit également être évaluée si la première l'est True
. Notez que, si la première expression est évaluée comme véridique, la valeur de retour est toujours le résultat de la deuxième expression . Si la première expression est évaluée comme étant Falsy, le résultat renvoyé est le résultat de la première expression.
Dans la fonction ci-dessus, If foo
reçoit un ou plusieurs arguments, len(args)
est supérieur à 0
(un nombre positif), le résultat renvoyé est donc max(args) - min(args)
. OTOH, si aucun argument n'est passé, len(args)
est 0
ce qui est Falsy et 0
est retourné.
Notez qu'une autre façon d'écrire cette fonction serait:
def foo(*args):
if not len(args):
return 0
return max(args) - min(args)
Ou, plus brièvement,
def foo(*args):
return 0 if not args else max(args) - min(args)
Si bien sûr, aucune de ces fonctions n'effectue de vérification de type, donc à moins que vous ne fassiez entièrement confiance à l'entrée fournie, ne vous fiez pas à la simplicité de ces constructions.
Comment or
fonctionne
J'explique le fonctionnement de or
de la même manière avec un exemple artificiel.
Étant donné une fonction avec la définition
def foo(*args):
...
Comment feriez-vous foo
pour retourner tous les numéros 9000
?
Nous utilisons or
pour gérer le cas d'angle ici. Nous définissons foo
comme:
def foo(*args):
return [x for x in args if x > 9000] or 'No number over 9000!'
foo(9004, 1, 2, 500)
# [9004]
foo(1, 2, 3, 4)
# 'No number over 9000!'
foo
effectue une filtration sur la liste pour conserver tous les numéros 9000
. S'il existe de tels nombres, le résultat de la compréhension de la liste est une liste non vide qui est Vérité, donc elle est retournée (court-circuit en action ici). S'il n'existe pas de tels nombres, alors le résultat de la liste comp est []
qui est Falsy. Ainsi, la deuxième expression est maintenant évaluée (une chaîne non vide) et est renvoyée.
En utilisant des conditions, nous pourrions réécrire cette fonction comme suit:
def foo(*args):
r = [x for x in args if x > 9000]
if not r:
return 'No number over 9000!'
return r
Comme précédemment, cette structure est plus flexible en termes de gestion des erreurs.
and
(ainsi queor
) ne se limite pas à travailler avec ou à renvoyer des valeurs booléennes.