Le bug Python subtil que j'ai créé en comprenant mal `bool()`

Le bug Python subtil que j’ai créé en comprenant mal bool()

J’ai introduit un bug subtil dans un programme Python à cause d’une hypothèse simple. Une variable nommée is_enabled devait contenir une chaîne représentant un booléen : soit "true", soit "false".

Pour évaluer cette variable, j’ai écrit cette condition :

1if bool(is_enabled.capitalize()):
2    # Faire quelque chose si True

Au premier coup d’œil, cela semble logique. Si is_enabled vaut "false", alors is_enabled.capitalize() devient "False". La fonction bool("False") devrait donc renvoyer False, n’est-ce pas ?

C’est faux. La condition a renvoyé True à chaque fois, bloquant la logique de mon programme.

Le piège de l’intuition symétrique

J’ai fait cette erreur principalement à cause d’une fausse impression de symétrie dans la conversion de types en Python. Le langage permet de passer facilement d’un type à un autre. La plupart des conversions semblent bidirectionnelles :

  • Avec les entiers

    • str(1) donne "1"
    • int("1") donne 1
  • Avec les flottants

    • str(1.5) donne "1.5"
    • float("1.5") donne 1.5
  • Avec les booléens

    • str(True) donne "True" et str(False) donne "False"

Le cerveau construit naturellement un modèle où passer la représentation textuelle d’une valeur à son constructeur de type inverse le processus. On s’attend à ce que bool("True") donne True et que bool("False") donne False.

Pourtant, cette symétrie s’effondre lors de la conversion d’une chaîne en booléen.

Pourquoi Python évalue "False" comme True

En Python, le constructeur bool() n’analyse pas le contenu textuel d’une chaîne (contrairement à int() ou float()). Il évalue la chaîne selon les règles fondamentales des tests de valeur de vérité (ou “truthiness”).

D’après la Documentation Python officielle, un objet est considéré comme vrai, sauf si sa classe définit une méthode __bool__() qui renvoie False ou une méthode __len__() qui renvoie 0.

Pour les chaînes de caractères, cela implique que :

  • La chaîne vide "" est False (car sa longueur est de 0).
  • Toute chaîne non vide est True (peu importe les caractères qu’elle contient).

À cause de cette règle, toutes ces instructions évaluent à True :

1print(bool("true"))   # True
2print(bool("False"))  # True
3print(bool("0"))      # True
4print(bool(" "))      # True (contient un espace)

Mon code bool(is_enabled.capitalize()) prenait la valeur "false" et la transformait en "False". Comme "False" est une chaîne non vide, Python l’a évaluée comme True, en accord strict avec ses règles.

Comment analyser correctement les chaînes booléennes

Si vous devez convertir une variable chaîne contenant "true" ou "false" en un véritable booléen, vous ne pouvez pas utiliser bool(). Utilisez plutôt l’une de ces approches explicites :

1. Comparaison directe de chaînes (Recommandé)

La méthode la plus propre et la plus lisible consiste à comparer directement la chaîne convertie en minuscules avec "true".

1# Évalue à True uniquement si is_enabled est une forme textuelle de "true"
2is_valid = is_enabled.lower() == "true" 
2. Utilisation d’un dictionnaire de correspondance

Un dictionnaire est idéal pour gérer explicitement les deux états valides et intercepter les valeurs inattendues.

1STR_TO_BOOL = {"true": True, "false": False}
2
3# Renvoie True, False, ou None si la chaîne ne correspond à aucun des deux
4is_valid = STR_TO_BOOL.get(is_enabled.lower()) 

Tip

Leçons apprises

  • N’utilisez jamais bool(chaine) pour analyser des valeurs booléennes textuelles comme "False".
  • Rappelez-vous que toute chaîne non vide est truthy en Python.
  • Python privilégie la longueur explicite de la collection plutôt que le contenu textuel lors de la conversion en booléen.

En espérant que cela vous évitera de tomber dans le même piège de truthiness lors de vos prochaines conversions de chaînes en booléens avec Python !

Articles Connexes

Enums vs Constantes : Pourquoi les Enums sont une solution plus sûre et plus intelligente

Enums vs Constantes : Pourquoi les Enums sont une solution plus sûre et plus intelligente

Utilisez-vous toujours des entiers ou des chaînes de caractères pour représenter des catégories fixes dans votre code ? Si c’est le cas, vous …

Lire la suite
`1ms` : La Fausse Promesse de `sleep()` pour le Code Temps Réel — Résolution et Jitter Réparées

1ms : La Fausse Promesse de sleep() pour le Code Temps Réel — Résolution et Jitter Réparées

Si vous avez déjà créé un système en temps réel, un simulateur de données ou une boucle de jeu, vous avez probablement essayé d’utiliser sleep() …

Lire la suite
Qu'est-ce qu'une variable en programmation ? Guide simple pour débutants

Qu’est-ce qu’une variable en programmation ? Guide simple pour débutants

Comment les programmes stockent-ils et manipulent-ils des informations ? La réponse se trouve dans les variables, les éléments essentiels de la …

Lire la suite