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

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 ?

Offre d'emploi Développeuse/Développeur

Hashbang crée un poste de développeuse/développeur en contrat à durée indéterminée pour agrandir et dynamiser son équipe de production.

Chariotte news 5 : Le virage associatif et la V1

Dans le calme d'un mois de juillet endormi, on entend dans un bureau des clic clic clic acharnés, fatigués, entêtés, engagés. La Chariotte grandit, s'élargit et se consolide, n'attendant que d'accueillir ses premières commandes groupées. Et ça arrive !