La magie des opérations booléennes

J'étais persuadé qu'avec Python, les opérations booléennes x and y et x or y ne retournait que des booléens. Mais en fait, non ! Et je m'émerveille de leur fonctionnement réel ! :)

Et pourtant, j'avais déjà utilisé des syntaxes du genre x = y or 0 qui donne la valeur 0 à x si y est évalué à False, et y sinon. J'avais utilisé cette syntaxe sans savoir ce qu'il se passait derrière, et je trouvais cette syntaxe pratique. Hier, j'ai relu du code et j'ai trouvé quelque chose du genre x = y and 1 or 0. Et là, je me suis dit "Hein ?".

Voici donc l'explication : or et and évaluent la première variable et retournent l'une deux variable. x or y retourne x si x est évalué à True, et y sinon. x and y retourne y si x est évalué à True, et x sinon. Pas très clair ? Vous retrouverez le détail des explications dans la documentation officielle des opérations booléennes. Et voici quelques exemples :

>>> 1 and 'a''a' >>> 0 and 'a'0 >>> 1 or 'a'1 >>> 0 or 'a''a' >>> '' or 'a''a' >>> [] or 'a''a' >>> True and 'a''a' >>> False and 'a'False >>> True or 'a'True >>> False or 'a''a' >>>

L'évaluation d'une variable fonctionne comme la conversion en booléen : elle utilise la méthode spéciale __nonzero__ en Python 2 (doc de __nonzero__) et __bool__ en Python 3 (doc de __bool__). Si cette méthode n'est pas définie, elle regarde le retour de la méthode __len__. Et si aucune de ces deux méthodes n'est définie, alors c'est True.

Voici des exemples dans la console interactive Python 3 :

>>> class test_true:... def __bool__(self): # __nonzero__ en Python 2... return True...>>> bool(test_true())True >>> class test_false:... def __bool__(self): # __nonzero__ en Python 2... return False...>>> bool(test_false())False >>> class test_len_0:... def __len__(self):... return 0...>>> bool(test_len_0())False >>> class test_len_1:... def __len__(self):... return 1...>>> bool(test_len_1())True >>> class test_pass:... pass...>>> bool(test_pass())TrueEt la syntaxe x = y and 1 or 0, peut être décortiquée de la manière suivante :

  • si bool(y) est True alors y and 1 renvoie 1 et 1 or 0 renvoie 1.
  • si bool(y) est False, alors y and 1 renvoie y et y or 0 renvoie 0.

Et cette syntaxe correspond à l'algorithme suivant :

if y: x = 1else: x = 0

Mais x = y and 1 or 0 est bien plus court et pratique.

C'est bête, mais à chaque que je regarde un peu les entrailles de Python, je m'émerveille un peu plus ! :)

Derniers articles

Pourquoi nous utilisons Wagtail : le CMS Django qui sépare les casquettes

Une introduction à Wagtail et son Zen : comment laisser à l'éditeur·i·ce de contenu un peu de choix, mais pas trop.

Comment devenir un bureau d'enregistrement ?

Devenir bureau d'enregistrement est un parcours de la combattante au niveau technique, administratif et financier. Il y a des cas simples et d'autres qui demandent de raser un Yack.

Précisions sur le projet de bureau d'enregistrement coopératif

L'appel à intérêt lancé la semaine dernière a suscité plusieurs réactions sur les valeurs proposées : clarifions quelques points aujourd'hui.

Appel à intérêt pour un bureau d'enregistrement coopératif

Qui serait partant·e pour participer (ou être client·e) du premier registrar sous forme de société coopérative d'intérêt collectif ?