Optimisez votre code avec des valeurs de vérité – Real Python

By | octobre 19, 2020

Python pas cher

le Python Booléen type est l'un des types de données intégrés à Python. Il est utilisé pour représenter la valeur de vérité d’une expression. Par exemple, l'expression 1 <= 2 est Vrai, tandis que l'expression 0 == 1 est Faux. Comprendre comment les valeurs booléennes Python se comportent est important pour bien programmer en Python.

Le type booléen Python

Le type booléen Python n'a que deux valeurs possibles:

  1. Vrai
  2. Faux

Aucune autre valeur n'aura booléen comme son type. Vous pouvez vérifier le type de Vrai et Faux avec le intégré type():

>>>

>>> type(Faux)

>>> type(Vrai)

le type() des deux Faux et Vrai est booléen.

Le type booléen est intégré, ce qui signifie qu'il est toujours disponible en Python et n'a pas besoin d'être importé. Cependant, le nom lui-même n’est pas un mot-clé dans la langue. Bien que ce qui suit soit considéré comme un mauvais style, il est possible d'attribuer au nom booléen:

>>>

>>> booléen

>>> booléen = "ce n'est pas un type"
>>> booléen
'ce n'est pas un type'

Bien que cela soit techniquement possible, pour éviter toute confusion, il est fortement recommandé de ne pas attribuer une valeur différente à booléen.

Booléens Python en tant que mots-clés

Les noms intégrés ne sont pas des mots clés. En ce qui concerne le langage Python, ce sont des variables régulières. Si vous les attribuez, vous remplacerez la valeur intégrée.

En revanche, les noms Vrai et Faux sont ne pas intégrés. Ils sont mots clés. Contrairement à de nombreux autres mots-clés Python, Vrai et Faux sont Python expressions. Puisqu'il s'agit d'expressions, elles peuvent être utilisées partout où d'autres expressions, comme 1 + 1, peut être utilisé.

Il est possible d’attribuer une valeur booléenne à des variables, mais il n’est pas possible d’attribuer une valeur à Vrai:

>>>

>>> a_true_alias = Vrai
>>> a_true_alias
Vrai
>>> Vrai = 5
  Fichier "", ligne 1
Erreur de syntaxe: impossible d'attribuer à True

Parce que Vrai est un mot-clé, vous ne pouvez pas lui attribuer de valeur. La même règle s'applique à Faux:

>>>

>>> Faux = 5
  Fichier "", ligne 1
Erreur de syntaxe: ne peut pas attribuer à False

Vous ne pouvez pas attribuer à Faux car c'est un mot-clé en Python. De cette façon, Vrai et Faux se comportent comme les autres constantes numériques. Par exemple, vous pouvez passer 1,5 aux fonctions ou l'affecter à des variables. Cependant, il est impossible d’attribuer une valeur à 1,5. La déclaration 1,5 = 5 n'est pas Python valide. Tous les deux 1,5 = 5 et Faux = 5 sont du code Python invalide et lèvera un Erreur de syntaxe une fois analysé.

Booléens Python sous forme de nombres

Les booléens sont considérés comme un numérique tapez Python. Cela signifie que ce sont des nombres à toutes fins utiles. En d'autres termes, vous pouvez appliquer des opérations arithmétiques aux booléens, et vous pouvez également les comparer à des nombres:

>>>

>>> Vrai == 1
Vrai
>>> Faux == 0
Vrai
>>> Vrai + (Faux / Vrai)
1.0

Les utilisations de la nature numérique des valeurs booléennes sont rares, mais il existe une technique qui peut vous être utile. Parce que Vrai est égal à 1 et Faux est égal à 0, ajouter des booléens ensemble est un moyen rapide de compter le nombre de Vrai valeurs. Cela peut être utile lorsque vous devez compter le nombre d'articles qui satisfont à une condition.

Par exemple, si vous souhaitez analyser un verset d'un poème classique pour enfants pour voir quelle fraction de lignes contient le mot "les", puis le fait que Vrai est égal à 1 et Faux est égal à 0 peut être très utile:

>>>

>>> lignes="" "
... Il prit son épée vorpale en main;
...                         Longtemps l'ennemi manxome qu'il cherchait -
... Alors reposé il près de l'arbre Tumtum
...                         Et est resté un moment dans ses pensées.
... "" ".lignes de division()
>>> somme("les" dans ligne.inférieur() pour ligne dans lignes) / len(lignes)
0,5

La somme de toutes les valeurs dans une expression de générateur comme celle-ci vous permet de savoir combien de fois Vrai apparaît dans le générateur. Le nombre de fois Vrai est dans le générateur est égal au nombre de lignes qui contiennent le mot "les", d'une manière insensible à la casse. En divisant ce nombre par le nombre total de lignes, vous obtenez le rapport entre les lignes correspondantes et le nombre total de lignes.

Pour voir pourquoi cela fonctionne, vous pouvez diviser le code ci-dessus en parties plus petites:

>>>

>>> lignes = "" "
... Il prit son épée vorpale en main;
...                         Longtemps l'ennemi manxome qu'il cherchait -
... Alors reposé il près de l'arbre Tumtum
...                         Et est resté un moment dans ses pensées.
... "" "
>>> line_list = lignes.lignes de division()
>>> "les" dans line_list[[[[0]
Faux
>>> "les" dans line_list[[[[1]
Vrai
>>> 0 + Faux + Vrai # Équivaut à 0 + 0 + 1
1
>>> [[[["les" dans ligne pour ligne dans line_list]
[False, True, True, False]
>>> Faux + Vrai + Vrai + Faux
2
>>> len(line_list)
4
>>> 2/4
0,5

le line_list variable contient une liste de lignes. La première ligne n'a pas le mot "les" dedans, donc "the" dans line_list[0] est Faux. Dans la deuxième ligne, "les" apparaît, donc "the" dans line_list[1] est Vrai. Puisque les booléens sont des nombres, vous pouvez les ajouter à des nombres, et 0 + Faux + Vrai donne 1.

Puisque ["the" in line for line in line_list] est une liste de quatre booléens, vous pouvez les additionner. Lorsque vous ajoutez Faux + Vrai + Vrai + Faux, vous recevez 2. Maintenant, si vous divisez ce résultat par 4, la longueur de la liste, vous obtenez 0,5. Le mot "les" apparaît sur la moitié des lignes de la sélection. C'est un moyen utile de tirer parti du fait que les booléens sont des nombres.

Opérateurs booléens

Les opérateurs booléens sont ceux qui prennent Entrées booléennes et retour Résultats booléens.

Étant donné que les valeurs booléennes Python n'ont que deux options possibles, Vrai ou Faux, il est possible de spécifier complètement les opérateurs en fonction des résultats qu’ils attribuent à chaque combinaison d’entrées possible. Ces spécifications sont appelées tables de vérité puisqu'ils sont affichés dans un tableau.

Comme vous le verrez plus loin, dans certaines situations, la connaissance d’une entrée d’un opérateur suffit à déterminer sa valeur. Dans ces cas, l'autre entrée est ne pas évalué. C'est appelé évaluation des courts-circuits.

L'importance de l'évaluation des courts-circuits dépend du cas particulier. Dans certains cas, cela peut avoir peu d'effet sur votre programme. Dans d’autres cas, par exemple, lorsque l’évaluation d’expressions qui n’affectent pas le résultat nécessiterait un calcul intensif, cela offre un avantage considérable en termes de performances. Dans les cas les plus extrêmes, l'exactitude de votre code peut dépendre de l'évaluation du court-circuit.

Opérateurs sans entrées

Vous pouvez penser à Vrai et Faux en tant qu'opérateurs booléens qui n'acceptent aucune entrée. L'un de ces opérateurs renvoie toujours Vrai, et l'autre revient toujours Faux.

Penser les valeurs booléennes Python en tant qu'opérateurs est parfois utile. Par exemple, cette approche permet de vous rappeler qu'il ne s'agit pas de variables. Pour la même raison, vous ne pouvez pas attribuer à +, il est impossible d'attribuer à Vrai ou Faux.

Seules deux valeurs booléennes Python existent. Un opérateur booléen sans entrée renvoie toujours la même valeur. À cause de ce, Vrai et Faux sont les deux seuls opérateurs booléens qui ne prennent pas d’entrées.

le ne pas Opérateur booléen

Le seul opérateur booléen avec un argument est ne pas. Il prend un argument et renvoie le résultat opposé: Faux pour Vrai et Vrai pour Faux. Le voici dans une table de vérité:

UNE pas A
Vrai Faux
Faux Vrai

Ce tableau illustre que ne pas renvoie la valeur de vérité opposée de l'argument. Puisque ne pas ne prend qu'un seul argument, il ne court-circuite pas. Il évalue son argument avant de renvoyer son résultat:

>>>

>>> ne pas Vrai
Faux
>>> ne pas Faux
Vrai
>>> def print_and_true():
...     impression("J'ai été appelé")
...     revenir Vrai
...
>>> ne pas print_and_true()
J'ai été appelé
Faux

La dernière ligne montre que ne pas évalue son entrée avant de retourner Faux.

Vous vous demandez peut-être pourquoi il n'y a pas d'autres opérateurs booléens qui acceptent un seul argument. Afin de comprendre pourquoi, vous pouvez consulter un tableau qui montre tous les opérateurs booléens théoriquement possibles qui prendraient un argument:

UNE pas A Identité Oui Non
Vrai Faux Vrai Vrai Faux
Faux Vrai Faux Vrai Faux

Il n'y a que quatre opérateurs possibles avec un argument. Autre que ne pas, les trois opérateurs restants ont tous des noms quelque peu fantaisistes car ils n’existent pas:

  • Identité: Puisque cet opérateur renvoie simplement son entrée, vous pouvez simplement le supprimer de votre code sans effet.

  • Oui: Ceci est un opérateur de court-circuit car il ne dépend pas de son argument. Vous pouvez simplement le remplacer par Vrai et obtenez le même résultat.

  • Non: Ceci est un autre opérateur de court-circuit car il ne dépend pas de son argument. Vous pouvez simplement le remplacer par Faux et obtenez le même résultat.

Aucun des autres opérateurs possibles avec un seul argument ne serait utile.

le et Opérateur booléen

le et L'opérateur prend deux arguments. Il évalue à Faux sauf si les deux entrées sont Vrai. Vous pouvez définir le comportement de et avec la table de vérité suivante:

UNE B A et B
Vrai Vrai Vrai
Faux Vrai Faux
Vrai Faux Faux
Faux Faux Faux

Ce tableau est détaillé. Cependant, il illustre le même comportement que la description ci-dessus. Si UNE est Faux, puis la valeur de B peu importe. À cause de ce, et court-circuit si la première entrée est Faux. En d'autres termes, si la première entrée est Faux, la deuxième entrée n’est pas évaluée.

Le code suivant a une deuxième entrée qui a un effet secondaire, l'impression, afin de fournir un exemple concret:

>>>

>>> def print_and_return(X):
...     impression(F"Je reviens X")
...     revenir X
...
>>> Vrai et print_and_return(Vrai)
Je retourne vrai
Vrai
>>> Vrai et print_and_return(Faux)
Je retourne faux
Faux
>>> Faux et print_and_return(Vrai)
Faux
>>> Faux et print_and_return(Faux)
Faux

Dans les deux derniers cas, rien n'est imprimé. La fonction n’est pas appelée car elle n’est pas nécessaire pour déterminer la valeur de et opérateur. Être conscient des courts-circuits est important lorsque les expressions ont un effet secondaire. Dans les deux derniers exemples, l'évaluation de court-circuit empêche l'effet secondaire d'impression de se produire.

Un exemple dans lequel ce comportement peut être crucial est dans le code qui peut déclencher des exceptions:

>>>

>>> def inverse_and_true(n):
...     1 // n
...     revenir Vrai
...
>>> inverse_and_true(5)
Vrai
>>> inverse_and_true(0)
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
  
  
  
  Fichier "", ligne 2, dans inverse_and_true
ZeroDivisionError: division entière ou modulo par zéro
>>> Faux et inverse_and_true(0)
Faux

La fonction inverse_and_true () est certes idiot, et de nombreux linters mettront en garde contre l'expression 1 // n étant inutile. Il sert à l'échec proprement lorsqu'il est donné 0 comme paramètre depuis la division par 0 est invalide. Cependant, la dernière ligne ne soulève pas d'exception. En raison de l’évaluation des courts-circuits, la fonction n’est pas appelée, la division par 0 ne se produit pas et aucune exception n’est soulevée.

En revanche, Vrai et inverse_and_true (0) soulèverait une exception. Dans ce cas, la valeur de la deuxième entrée serait nécessaire pour le résultat de et. Une fois la deuxième entrée évaluée, inverse_and_true (0) serait appelé, il se diviserait par 0, et une exception serait soulevée.

le ou Opérateur booléen

La valeur du ou l'opérateur est Vrai à moins que ses deux entrées ne soient Faux. le ou l'opérateur pourrait également être défini par la table de vérité suivante:

UNE B A ou B
Vrai Vrai Vrai
Faux Vrai Vrai
Vrai Faux Vrai
Faux Faux Faux

Ce tableau est détaillé, mais il a la même signification que l'explication ci-dessus.

Lorsqu'il est utilisé de manière informelle, le mot ou peut avoir l'une des deux significations suivantes:

  • le exclusif ou c'est comment ou est utilisé dans la phrase "Vous pouvez demander une extension ou soumettre vos devoirs à temps." Dans ce cas, vous ne pouvez pas à la fois demander une extension et soumettre vos devoirs à temps.

  • le compris ou est parfois indiqué en utilisant la conjonction et / ou. Par exemple, «Si vous réussissez bien cette tâche, vous pouvez obtenir une augmentation et / ou une promotion» signifie que vous pourriez obtenir à la fois une augmentation et une promotion.

Quand Python interprète le mot-clé ou, il le fait en utilisant le ou. Si les deux entrées sont Vrai, puis le résultat de ou est Vrai.

Parce qu'il utilise une ou, le ou L'opérateur en Python utilise également l'évaluation des courts-circuits. Si le premier argument est Vrai, alors le résultat est Vrai, et il n'est pas nécessaire d'évaluer le deuxième argument. Les exemples suivants illustrent l'évaluation de court-circuit de ou:

>>>

>>> def print_and_true():
...     impression("print_and_true appelé")
...     revenir Vrai
...
>>> Vrai ou print_and_true()
Vrai
>>> Faux ou print_and_true()
print_and_true appelé
Vrai

La deuxième entrée n'est pas évaluée par ou sauf si le premier est Faux. En pratique, l'évaluation en court-circuit de ou est beaucoup moins utilisé que celui de et. Cependant, il est important de garder ce comportement à l'esprit lors de la lecture du code.

Autres opérateurs booléens

La théorie mathématique de la logique booléenne détermine qu'aucun autre opérateur au-delà ne pas, et, et ou sont nécessaires. Tous les autres opérateurs sur deux entrées peuvent être spécifiés en fonction de ces trois opérateurs. Tous les opérateurs sur trois entrées ou plus peuvent être spécifiés en termes d'opérateurs de deux entrées.

En fait, même avoir les deux ou et et est redondant. le et opérateur peut être défini en termes de ne pas et ou, et le ou opérateur peut être défini en termes de ne pas et et. cependant, et et ou sont si utiles que tous les langages de programmation ont les deux.

Il existe seize opérateurs booléens à deux entrées possibles. À l'exception de et et ou, ils sont rarement nécessaires dans la pratique. À cause de ce, Vrai, Faux, ne pas, et, et ou sont les seuls opérateurs booléens Python intégrés.

Opérateurs de comparaison

Certains opérateurs Python vérifient si une relation existe entre deux objets. Étant donné que la relation tient ou ne tient pas, ces opérateurs, appelés opérateurs de comparaison, renvoie toujours des valeurs booléennes.

Les opérateurs de comparaison sont la source la plus courante de valeurs booléennes.

Égalité et inégalité

Les opérateurs de comparaison les plus courants sont les opérateur d'égalité (==) et le opérateur d'inégalité (! =). Il est presque impossible d’écrire une quantité significative de code Python sans utiliser au moins un de ces opérateurs.

L'opérateur d'égalité (==) est l'un des opérateurs les plus utilisés dans le code Python. Vous devez souvent comparer soit un résultat inconnu avec un résultat connu, soit deux résultats inconnus l'un par rapport à l'autre. Certaines fonctions renvoient des valeurs qui doivent être comparées à une sentinelle pour voir si une condition de bord a été détectée. Parfois, vous devez comparer les résultats de deux fonctions l'une par rapport à l'autre.

L'opérateur d'égalité est souvent utilisé pour comparer des nombres:

>>>

>>> 1 == 1
Vrai
>>> 1 == 1.0
Vrai
>>> 1 == 2
Faux

Vous avez peut-être déjà utilisé des opérateurs d'égalité. Ce sont certains des opérateurs les plus courants de Python. Pour tous les objets Python intégrés et pour la plupart des classes tierces, ils renvoient un Booléen valeur: Vrai ou Faux.

Le deuxième opérateur d'égalité en popularité est le inégalité opérateur (! =). Il retourne Vrai si les arguments ne sont pas égaux et Faux si ils sont. Les exemples sont tout aussi vastes. De nombreux tests unitaires vérifient que la valeur n'est pas égale à une valeur non valide spécifique. Un client Web peut vérifier que le code d'erreur n'est pas 404 introuvable avant d'essayer une alternative.

Voici deux exemples de l'opérateur d'inégalité Python utilisé:

>>>

>>> 1 ! = 2
Vrai
>>> 1 ! = (1 + 0,0)
Faux

Peut-être la chose la plus surprenante à propos de l'opérateur d'inégalité Python est le fait qu'il existe en premier lieu. Après tout, vous pourriez obtenir le même résultat que 1! = 2 avec pas (1 == 2). Python évite généralement une syntaxe supplémentaire, et en particulier des opérateurs de base supplémentaires, pour des choses facilement réalisables par d'autres moyens.

Cependant, l'inégalité est si souvent utilisée qu'il a été jugé utile de disposer d'un opérateur dédié. Dans les anciennes versions de Python, dans le 1 fois série, il y avait en fait deux syntaxes différentes.

Comme une blague du poisson d'avril, Python prend toujours en charge une syntaxe alternative pour l'inégalité avec le droit __futur__ importer:

>>>

>>> de __futur__ importer barry_as_FLUFL
>>> 1 <> 2
Vrai

Cette ne devrait jamais être utilisé dans n'importe quel code destiné à un usage réel. Cela pourrait cependant vous être utile pour votre prochaine soirée de trivia Python.

Comparaisons de commandes

Un autre ensemble d'opérateurs de test est le commande opérateurs de comparaison. Il existe quatre opérateurs de comparaison d'ordre qui peuvent être classés selon deux qualités:

  • Direction: Est-il inférieur ou supérieur à?
  • Rigueur: L'égalité est-elle autorisée ou non?

Puisque les deux choix sont indépendants, vous obtenez 2 * 2 == 4 opérateurs de comparaison d'ordres. Les quatre sont répertoriés dans ce tableau:

Moins que Plus grand que
Strict < >
Pas stricte <= > =

Il existe deux options pour la direction et deux options pour la rigueur. Il en résulte au total quatre opérateurs de comparaison d'ordre.

Les opérateurs de comparaison d’ordre ne sont pas définis pour tous les objets. Certains objets n'ont pas d'ordre significatif. Même si les listes et les tuples sont ordonnés lexicographiquement, les dictionnaires n'ont pas d'ordre significatif:

>>>

>>> 1: 3 < 2: 4
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: '<' non pris en charge entre les instances de 'dict' et 'dict'

La manière dont les dictionnaires doivent être classés n’est pas évidente. Selon le Zen de Python, face à l'ambiguïté, Python refuse de deviner.

Bien que les chaînes et les entiers soient classés séparément, les comparaisons entre types ne sont pas prises en charge:

>>>

>>> 1 <= "1"
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: '<=' non pris en charge entre les instances de 'int' et 'str'

Encore une fois, comme il n'y a pas de moyen évident de définir l'ordre, Python refuse de les comparer. Ceci est similaire à l'opérateur d'addition (+). Bien que vous puissiez ajouter des chaînes aux chaînes et des entiers aux entiers, l'ajout de chaînes aux entiers lève une exception.

Lorsque les opérateurs de comparaison d'ordres sont défini, en général, ils renvoient un booléen.

La comparaison de nombres en Python est un moyen courant de vérifier les conditions aux limites. Notez que < n'autorise pas l'égalité, alors que <= Est-ce que:

>>>

>>> 1 <= 1
Vrai
>>> 1 < 1
Faux
>>> 2 > 3
Faux
>>> 2 > = 2
Vrai

Les programmeurs utilisent souvent des opérateurs de comparaison sans se rendre compte qu'ils renvoient une valeur booléenne Python.

le est Opérateur

le est l'opérateur vérifie identité d'objet. En d'autres termes, x est y évalue à Vrai seulement quand X et y évaluer au même objet. le est l'opérateur a un opposé, le n'est pas opérateur.

Une utilisation typique de est et n'est pas consiste à comparer des listes d'identité:

>>>

>>> X = []
>>> y = []
>>> X est X
Vrai
>>> X est ne pas X
Faux
>>> X est y
Faux
>>> X est ne pas y
Vrai

Même si x == y, ce ne sont pas le même objet. le n'est pas L'opérateur renvoie toujours l'opposé de est. Il n'y a aucune différence entre l'expression x n'est pas y et l'expression non (x est y) sauf pour la lisibilité.

Gardez à l'esprit que les exemples ci-dessus montrent est opérateur utilisé uniquement avec les listes. Le comportement du est opérateur sur des objets immuables comme des nombres et des chaînes est plus compliqué.

le dans Opérateur

le dans l'opérateur vérifie adhésion. Un objet peut définir ce qu'il considère comme des membres. La plupart des séquences, telles que les listes, considèrent leurs éléments comme des membres:

>>>

>>> small_even = [[[[2, 4]
>>> 1 dans small_even
Faux
>>> 2 dans small_even
Vrai
>>> dix dans small_even
Faux

Puisque 2 est un élément de la liste, 2 dans small_even Retour Vrai. Puisque 1 et dix ne figurent pas dans la liste, les autres expressions renvoient Faux. Dans tous les cas, le dans L'opérateur renvoie une valeur booléenne.

Étant donné que les chaînes sont des séquences de caractères, vous pouvez vous attendre à ce qu'elles vérifient également l'appartenance. En d'autres termes, les caractères membres de la chaîne renverront Vrai pour dans, tandis que ceux qui ne reviendront pas Faux:

>>>

>>> "e" dans "bonjour beau monde"
Vrai
>>> "X" dans "bonjour beau monde"
Faux

Puisque "e" est le deuxième élément de la chaîne, le premier exemple renvoie Vrai. Puisque X n'apparaît pas dans la chaîne, le deuxième exemple renvoie Faux. Cependant, avec les caractères individuels, les sous-chaînes sont également considérées comme membres d'une chaîne:

>>>

>>> "beau" dans "bonjour beau monde"
Vrai
>>> "belle" dans "bonjour beau monde"
Faux

Puisque "beau" est une sous-chaîne, le dans retour de l'opérateur Vrai. Puisque "belle" n'est pas une sous-chaîne, le dans retour de l'opérateur Faux. Ceci malgré le fait que chaque lettre "belle" est membre de la chaîne.

Comme les opérateurs est et ==, le dans l'opérateur a également un opposé, pas dedans. Vous pouvez utiliser pas dedans pour confirmer qu'un élément n'est pas membre d'un objet.

Opérateurs de comparaison de chaînage

Les opérateurs de comparaison peuvent se former Chaînes. Vous pouvez créer des chaînes d'opérateurs de comparaison en séparant les expressions avec des opérateurs de comparaison pour former une expression plus grande:

L'expression 1 <2 <3 est une chaîne d'opérateurs de comparaison. Il a des expressions séparées par des opérateurs de comparaison. Le résultat est Vrai car les deux parties de la chaîne sont Vrai. Vous pouvez briser la chaîne pour voir comment cela fonctionne:

>>>

>>> 1 < 2 et 2 < 3
Vrai

Puisque 1 <2 Retour Vrai et 2 <3 Retour Vrai, et Retour Vrai. Une chaîne de comparaison équivaut à utiliser et sur tous ses liens. Dans ce cas, depuis Vrai et vrai Retour Vrai, le résultat de toute la chaîne est Vrai. Cela signifie que si l'un des liens est Faux, alors toute la chaîne est Faux:

Cette chaîne de comparaison renvoie Faux puisque tous ses liens ne sont pas Vrai. Parce que les chaînes de comparaison sont implicites et opérateur, si même un lien est Faux, alors toute la chaîne est Faux. Vous pouvez briser la chaîne pour voir comment cela fonctionne:

>>>

>>> 1 < 3 et 3 < 2
Faux

Dans ce cas, les parties de la chaîne évaluent les valeurs booléennes suivantes:

  • 1 <3 est Vrai
  • 3 <2 est Faux

Cela signifie que l'un des résultats est Vrai et l'un est Faux. Puisque Vrai et faux est égal à Faux, la valeur de toute la chaîne est Faux.

Vous pouvez mélanger des types et des opérations dans une chaîne de comparaison tant que les types peuvent être comparés:

>>>

>>> 1 < 2 < 1
Faux
>>> 1 == 1.0 < 0,5
Faux
>>> 1 == 1.0 == Vrai
Vrai
>>> 1 < 3 > 2
Vrai
>>> 1 < 2 < 3 < 4 < 5
Vrai

Les opérateurs ne doivent pas être tous les mêmes. Même les types ne doivent pas être tous les mêmes. Dans les exemples ci-dessus, vous avez trois types numériques:

  1. int
  2. flotte
  3. booléen

Ce sont trois types numériques différents, mais vous pouvez comparer des objets de différents types numériques sans problème.

Évaluation de la chaîne de court-circuit

Si les chaînes utilisent un implicite et, alors les chaînes doivent également court-circuiter. Ceci est important car même dans les cas où une comparaison d'ordre n'est pas définie, il est possible qu'une chaîne retourne Faux:

>>>

>>> 2 < "2"
Traceback (dernier appel le plus récent):
  Fichier "", ligne 1, dans 
Erreur-type: '<' non pris en charge entre les instances de 'int' et 'str'
>>> 3 < 2 < "2"
Faux

Même si Python ne peut pas comparer les nombres entiers et chaînes, 3 <2 <"2" évalue à Faux car il n’évalue pas la deuxième comparaison. Dans ce cas, l'évaluation du court-circuit évite un autre effet secondaire: lever une exception.

L'évaluation en court-circuit des chaînes de comparaison peut empêcher d'autres exceptions:

>>>

>>> 3 < 2 < (1//0)
Faux

Partage 1 par 0 aurait soulevé un ZeroDivisionError. Cependant, en raison de l'évaluation du court-circuit, Python n'évalue pas la division invalide. Cela signifie que Python ignore l'évaluation non seulement de la comparaison, mais également des entrées de la comparaison.

Un autre aspect qu'il est important de comprendre à propos des chaînes de comparaison est que lorsque Python Est-ce que évaluer un élément de la chaîne, il ne l'évalue qu'une seule fois:

>>>

>>> def toto():
...     impression("Je suis foo")
...     revenir 1
...
>>> 0 < toto() < 2
Je suis foo
Vrai
>>> (0 < toto()) et (toto() < 2)
Je suis foo
Je suis foo
Vrai

Étant donné que les éléments du milieu ne sont évalués qu’une seule fois, il n’est pas toujours sûr de les refactoriser x <y <z à (x <y) et (y <z). Bien que la chaîne se comporte comme et dans son évaluation de court-circuit, il évalue toutes les valeurs, y compris les valeurs intermédiaires, une seule fois.

Les chaînes sont particulièrement utiles pour contrôles de plage, qui confirment qu'une valeur se situe dans une plage donnée. Par exemple, dans une facture journalière qui inclut le nombre d'heures travaillées, vous pouvez effectuer les opérations suivantes:

>>>

>>> heures travaillées = 5
>>> 1 <= heures travaillées <= 25
Vrai

S'il y a 0 heures travaillées, alors il n’y a aucune raison d’envoyer la facture. En tenant compte de l'heure d'été, le nombre maximum d'heures dans une journée est 25. La vérification de la plage ci-dessus confirme que le nombre d'heures travaillées dans une journée se situe dans la plage autorisée.

Opérateurs de mixage et chaînage

Jusqu'à présent, tous nos exemples impliqués ==, ! =, et les comparaisons d'ordre. Cependant, vous pouvez chaîner tous les opérateurs de comparaison de Python. Cela peut conduire à un comportement surprenant:

>>>

>>> une = 0
>>> une est une < 1
Vrai
>>> (une est une) < 1
Faux
>>> une est (une < 1)
Faux

Parce que a est un <1 est une chaîne de comparaison, elle évalue Vrai. Vous pouvez casser la chaîne en ses parties:

  • L'expression a est un est Vrai, comme ce serait le cas pour toute valeur évaluée par rapport à elle-même.
  • L'expression a <1 est Vrai puisque 0 est inférieur à 1.

Puisque les deux parties sont Vrai, la chaîne évalue à Vrai.

Cependant, les personnes habituées à d'autres opérateurs en Python peuvent supposer que, comme d'autres expressions impliquant plusieurs opérateurs tels que 1 + 2 * 3, Python insère des parenthèses dans l'expression. Cependant, aucune manière d'insérer des parenthèses ne sera évaluée comme Vrai.

Vous pouvez voir pourquoi les deux évaluent à Faux si vous brisez les expressions. Si vous divisez la première expression, vous obtenez ce qui suit:

>>>

>>> une = 0
>>> une est une
Vrai
>>> Vrai == 1
Vrai
>>> (une est une) < 1
Faux

Vous pouvez voir ci-dessus a est un Retour Vrai, comme il le ferait pour n'importe quelle valeur. Cela signifie que (a est a) <1 est le même que Vrai <1. Les booléens sont des types numériques, et Vrai est égal à 1. Alors Vrai <1 est le même que 1 <1. Puisque c'est un strict l'inégalité, et 1 == 1, il renvoie False.

La deuxième expression fonctionne différemment:

>>>

>>> une = 0
Faux
>>> une < 1
Vrai
>>> 0 est Vrai
: 1: SyntaxWarning: "est" avec un littéral. Vouliez-vous dire "=="?
Faux

Puisque 0 est inférieur à 1, a <1 Retour Vrai. Puisque 0! = Vrai, alors il ne peut pas être le cas que 0 est vrai.

La leçon la plus importante à en tirer est que l'enchaînement des comparaisons avec est ce n’est généralement pas une bonne idée. Cela déroute le lecteur et n'est probablement pas nécessaire.

Comme est, le dans opérateur et son opposé, pas dedans, peuvent souvent donner des résultats surprenants lorsqu'ils sont enchaînés:

>>>

>>> "b" dans "aba" dans "cabad" < "cabae"
Vrai

Pour maximiser la confusion, cet exemple enchaîne les comparaisons avec différents opérateurs et utilisations dans avec des chaînes pour vérifier les sous-chaînes. Encore une fois, ce n'est pas un exemple de code bien écrit! Cependant, il est important de pouvoir lire cet exemple et de comprendre pourquoi il revient Vrai.

Enfin, vous pouvez enchaîner n'est pas avec pas dedans:

>>>

>>> salutation = "Bonjour"
>>> qualité = "bien"
>>> end_greeting = "adieu"
>>> salutation est ne pas qualité ne pas dans end_greeting
Vrai

Notez que l'ordre de ne pas dans les deux opérateurs n'est pas la même chose! Les opérateurs négatifs sont n'est pas et pas dedans. Cela correspond à l'usage habituel en anglais, mais il est facile de se tromper lors de la modification du code.

Test booléen Python

L'utilisation la plus courante d'un booléen Python est dans un si déclaration. Cette instruction s'exécutera si la valeur est Vrai:

>>>

>>> 1 == 1
Vrai
>>> si 1 == 1:
...     impression("oui")
...
oui
>>> 1 == 2
Faux
>>> si 1 == 2:
...     impression("oui")
...

impression() est appelée uniquement lorsque l'expression est évaluée à Vrai. Cependant, en Python, vous pouvez donner n'importe quelle valeur à si. Les valeurs qui si considère Vrai sont appelés vérité, et les valeurs qui si considère Faux sont appelés faux.

si décide quelles valeurs sont véridiques et lesquelles sont fausses en appelant en interne le booléen (). Vous avez déjà rencontré booléen () comme type booléen Python. Lorsqu'il est appelé, il convertit les objets en booléens.

Aucun comme valeur booléenne

L'objet singleton Aucun est toujours faux:

Ceci est souvent utile dans si instructions qui vérifient une valeur sentinelle. Cependant, il est généralement préférable de vérifier explicitement l'identité avec est Aucun. quelquefois Aucun peut être utile en combinaison avec une évaluation de court-circuit afin d'avoir un défaut.

Par exemple, vous pouvez utiliser ou substituer Aucun avec une liste vide:

>>>

>>> def add_num_and_len(num, des choses=Aucun):
...     revenir num + len(des choses ou [])
...
>>> add_num_and_len(5, [[[[1, 2, 3])
8
>>> add_num_and_len(6)
6

Dans cet exemple, la liste ne sera pas créée si des choses est une liste non vide puisque ou court-circuitera avant d'évaluer [].

Nombres en tant que valeurs booléennes

Pour les chiffres, booléen (x) est équivalent à x! = 0. Cela signifie que le seul entier faux est 0:

>>>

>>> booléen(3), booléen(-5), booléen(0)
(True, True, False)

All nonzero integers are truthy. This is also true for floating-point numbers, including special floating-point numbers like infinity and Not a Number (NaN):

>>>

>>> import math
>>> [[[[bool(X) for X dans [[[[0, 1.2, 0,5, math.inf, math.nan]]
[False, True, True, True, True]

Since infinity and NaN aren’t equal to 0, they’re truthy.

Equality and inequality comparisons on floating-point numbers are subtle operations. Since doing bool(x) is equivalent to x != 0, this can lead to surprising results for floating-point numbers:

>>>

>>> bool(0.1 + 0,2 + (-0,2) + (-0.1))
True
>>> 0.1 + 0,2 + (-0,2) + (-0.1)
2.7755575615628914e-17

Floating-point number computations can be inexact. Because of that, the results of bool() on floating-point numbers can be surprising.

Python has more numeric types in the standard library, and they follow the same rules. For non-built-in numeric types, bool(x) is also equivalent to x != 0. le fractions module is in the standard library. Like other numeric types, the only falsy fraction is 0/1:

>>>

>>> import fractions
>>> bool(fractions.Fraction("1/2")), bool(fractions.Fraction("0/1"))
(True, False)

As with integers and floating-point numbers, fractions are false only when they’re equal to 0.

le decimal module is also in the standard library. Decimals are similarly falsy only when they’re equal to 0:

>>>

>>> import decimal, math
>>> avec decimal.localcontext(decimal.Context(prec=3)) as ctx:
...     bool(ctx.create_decimal(math.pi) - ctx.create_decimal(22)/7)
...
False
>>> avec decimal.localcontext(decimal.Context(prec=4)) as ctx:
...     bool(ctx.create_decimal(math.pi) - ctx.create_decimal(22)/7)
...
True

The number 22 / 7 is an approximation of Pi to two decimal places. This fact was discussed by Archimedes in the 3rd century BCE. When the difference between 22 / 7 and Pi is computed with this precision, the result is falsy. When the difference is computed with higher precision, the difference isn’t equal to 0, and so is truthy.

Sequences as Boolean Values

In general, objects that have a len() will be falsy when the result of len() est 0. It doesn’t matter if they’re lists, tuples, sets, strings, or byte strings:

>>>

>>> bool([[[[1]), bool([])
(True, False)
>>> bool((1,2)), bool(())
(True, False)
>>> bool(1,2,3), bool(set())
(True, False)
>>> bool(1: 2), bool()
(True, False)
>>> bool("hello"), bool("")
(True, False)
>>> bool(b"xyz"), bool(b"")
(True, False)

All built-in Python objects that have a length follow this rule. Later, you’ll see some exceptions to this rule for non-built-in objects.

Other Types as Boolean Values

Unless types have a len() or specifically define whether they’re truthy or falsy, they’re always truthy. This is true for built-in as well as user-defined types. In particular, functions are always truthy:

>>>

>>> def func():
...     pass
...
>>> bool(func)
True

Methods are always truthy, too. You might encounter this if a parenthesis is missing when you call a function or method:

>>>

>>> import datetime
>>> def before_noon():
...     return datetime.datetime.maintenant().heure < 12
...
>>> def greet():
...     si before_noon:
...             impression("Good morning!")
...     else:
...             impression("Good evening!")
...
>>> greet()
Bonjour!
>>> datetime.datetime.maintenant().heure
20

This can happen as a result of a forgotten parenthesis or misleading documentation that doesn’t mention that you need to call the function. If you expect a Python Boolean value but have a function that returns a Boolean value, then it will always be truthy.

By default, user-defined types are always truthy:

>>>

>>> class Dummy:
...     pass
...
>>> bool(Dummy())
True

Creating an empty class makes every object of that class truthy. All objects are truthy unless special methods are defined. If you want to make some instances of your class falsy, you can define .__bool__():

>>>

>>> class BoolLike:
...     am_i_truthy = False
...     def __bool__(soi):
...             return soi.am_i_truthy
...
>>> X = BoolLike()
>>> bool(X)
False
>>> X.am_i_truthy = True
>>> bool(X)
True

You can also use .__bool__() to make an object neither truthy nor falsy:

>>>

>>> class ExcludedMiddle:
...     def __bool__(soi):
...             raise ValueError("neither")
...
>>> X = ExcludedMiddle()
>>> bool(X)
Traceback (most recent call last):
  File "", line 1, in 
  
  
  
  File "", line 3, in __bool__
ValueError: neither

>>> si X:
...     impression("x is truthy")
... else:
...     impression("x is falsy")
...
Traceback (most recent call last):
  File "", line 1, in 
  
  
  
  File "", line 3, in __bool__
ValueError: neither

le si statement also uses .__bool__(). It does so to evaluate whether the object is truthy or falsy, which determines which branch to execute.

If you define the __len__ method on a class, then its instances have a len(). In that case, the Boolean value of the instances will be falsy exactly when their length is 0:

>>>

>>> class DummyContainer:
...     my_length = 0
...     def __len__(soi):
...         return soi.my_length
...
>>> X = DummyContainer()
>>> bool(X)
False
>>> X.my_length = 5
>>> bool(X)
True

In this example, len(x) would return 0 before the assignment and 5 afterward. The reverse, however, is not true. Defining .__bool__() doesn’t give instances a length:

>>>

>>> class AlwaysTrue:
...     def __bool__(soi):
...         return True
...
>>> class AlwaysFalse:
...     def __bool__(soi):
...         return False
...
>>> bool(AlwaysTrue()), bool(AlwaysFalse())
(True, False)

>>> len(AlwaysTrue())
Traceback (most recent call last):
  File "", line 1, in 
TypeError: object of type 'AlwaysTrue' has no len()

>>> len(AlwaysFalse())
Traceback (most recent call last):
  File "", line 1, in 
TypeError: object of type 'AlwaysFalse' has no len()

Defining .__bool__() doesn’t make instances of either class have a len(). When both .__bool__() et .__len__() are defined, .__bool__() takes precedence:

>>>

>>> class BooleanContainer:
...     def __len__(soi):
...         return 100
...     def __bool__(soi):
...         return False
...
>>> X=BooleanContainer()
>>> len(X)
100
>>> bool(X)
False

Even though X has a length of 100, it’s still falsy.

Example: NumPy Arrays

The above example may seem like something that only happens when you write a class intended to demonstrate edge cases in Python. However, it’s possible to get similar results using one of the most popular libraries on PyPI: NumPy.

Arrays, like numbers, are falsy or truthy depending on how they compare to 0:

>>>

>>> de numpy import array
>>> X = array([[[[0])
>>> len(X)
1
>>> bool(X)
False

Even though X has a length of 1, it’s still falsy because its value is 0.

When arrays have more than one element, some elements might be falsy and some might be truthy. In those cases, NumPy will raise an exception:

>>>

>>> de numpy import array
>>> import textwrap
>>> y=array([[[[0, 1])
>>> try:
...     bool(y)
... except ValueError as exc:
...     impression(" n".join(textwrap.wrap(str(exc))))
...
The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()

The exception is so wordy that in order to make it easy to read, the code uses text processing to wrap the lines.

An even more interesting edge case involves empty arrays. You might wonder if those are falsy like other sequences or truthy because they’re not equal to 0. As you saw above, those aren’t the only two possible answers. The arrays could also refuse to have a Boolean value.

Interestingly, none of these options is entirely true:

>>>

>>> bool(array([]))
:1: DeprecationWarning: The truth value of an empty array is ambiguous.
Returning False, but in future this will result in an error.
Use `array.size > 0` to check that an array is not empty.
False

While empty arrays are currently falsy, relying on this behavior is dangerous. In some future NumPy version, this will raise an exception.

Operators and Functions

There are a few more places in Python where Boolean testing takes place. One of those is in Boolean operators.

The operators et, or, et ne pas accept any value that supports Boolean testing. In the case of ne pas, it will always return a Boolean value:

>>>

>>> ne pas 1
False
>>> ne pas 0
True

The truth table for ne pas is still correct, but now it takes the truthiness of the input.

In the case of et et or, in addition to short-circuit evaluation, they also return the value at which they stopped evaluating:

>>>

>>> 1 et 2
2
>>> 0 et 1
0
>>> 1 or 2
1
>>> 0 or 2
2

The truth tables are still correct, but they now define the truthiness of the results, which depends on the truthiness of the inputs. This can come handy when, for example, you want to give values defaults.

Assume you have a function called summarize() that, if the text is too long, takes the beginning and the end and adds an ellipsis (...) in the middle. This might be useful in some reports that can’t fit the full text. However, some datasets have missing values represented by None.

Puisque summarize() assumes the input is a string, it will fail on None:

>>>

>>> def summarize(long_text):
...     si len(long_text) <= 4:
...         return long_text
...     return long_text[:[:[:[:2] +"..." + long_text[[[[-2:]
...
>>> summarize("hello world")
'he...ld'
>>> summarize("hi")
'hi'
>>> summarize("")
''
>>> summarize(None)
Traceback (most recent call last):
  File "", line 1, in 
  
  
  
  File "", line 2, in summarize
TypeError: object of type 'NoneType' has no len()

>>> for une dans [[[["hello world", "hi", "", None]:
...     impression("-->", summarize(une or ""))
...
--> he...ld
--> hi
->
->

This example takes advantage of the falsiness of None and the fact that or not only short-circuits but also returns the last value to be evaluated. The code for printing the report adds or "" to the argument to summarize(). The addition of or "" helps you to avoid errors with just a small code change.

The built-in functions all() et any() evaluate truthiness and also short-circuit, but they don’t return the last value to be evaluated. all() checks whether all of its arguments are truthy:

>>>

>>> tout([[[[1, 2, 3])
True
>>> tout([[[[0, 1, 2])
False
>>> tout(X / (X - 1) for X dans [[[[0, 1])
False

In the last line, all() doesn’t evaluate x / (x - 1) for 1. Puisque 1 - 1 est 0, this would have raised a ZeroDivisionError.

any() checks whether any of its arguments are truthy:

>>>

>>> any([[[[1, 0, 0])
True
>>> any([[[[False, 0, 0.0])
False
>>> any(1 / X for X dans [[[[1, 0])
True

In the last line, any() doesn’t evaluate 1 / x for 0.

Conclusion

The Python Boolean is a commonly used data type with many useful applications. You can use Booleans with operators like ne pas, et, or, dans, est, ==, et != to compare values and check for membership, identity, or equality. You can also use Boolean testing with an si statement to control the flow of your programs based on the truthiness of an expression.

In this tutorial, you’ve learned how to:

  • Manipulate Boolean values with Boolean operators
  • Convert Booleans to other types
  • Convert other types to Python Booleans
  • Use Booleans to write efficient and readable Python code

You now know how short-circuit evaluation works and recognize the connection between Booleans and the si statement. This knowledge will help you to both understand existing code and avoid common pitfalls that can lead to errors in your own programs.