Dans un langage fortement typé comme Python, on ne peut pas additionner des choux et des carottes, comme disait madame Germaine, ma prof de mate.
Par exemple on ne peut pas faire ça :
>>> 1 + "1" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str' |
Nonnnnnnnn !
Ni ça :
>>> [1] + (1,) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "tuple") to list |
Pas biennnnnnnnnnnnnn !
Et pas ça :
>>> True + 1 2 |
OUATE ZE PHOQUE ?
Les booléens sont des entiers déguisés
Pendant longtemps, Python n’a pas eu de type bool, et on utilisait, comme en C, 0 pour faux, et 1 pour vrai. Ça marchait pas mal, mais dans un souci de rentre le langage plus propre, on a voulu créer une type spécialisé, et ainsi :
>>> type(True) <class 'bool'> >>> type(1) <class 'int'> |
Mais il faut avouer que pouvoir interchanger True pour 1 et False pour 0 et vice versouille, c’était achement pratique dans une discipline ou la manipulation des chiffres à des fins logiques est un peu la base du métier. Du coup il a été décidé que les booléen seraient des travs, juste une surcouche au dessus des entiers, et qu’on pourrait les utiliser en lieu et place de ceux-ci. Une exception étonnante vu la rigueur du langage sur la gestion des types.
Du coup :
>>> True == 1 True >>> False == 0 True >>> True + 1 2 >>> False - 1 -1 |
Par contre :
>>> 1 is 1 True >>> True is True True >>> True is 1 False |
Et qui dit exception, dit hack
Donc voici quelques moyens de détourner l’utilisation des booléens pour écrire du Perlthon…
On peut utiliser un bool pour de l’indexing ou du slicing :
>>> ('Valeur 1', 'Valeur 2')[True] 'Valeur 2' >>> list(range(10)[True:False-1:2]) [1, 3, 5, 7] |
On peut utiliser un bool pour multiplier, et l’opération multiplier marche sur les strings et les listes…
>>> "J'aime les chat" + "s" * est_pluriel "J'aime les chat" >>> est_pluriel = True >>> "J'aime les chat" + "s" * est_pluriel "J'aime les chats" >>> def process(lst, cancel=False): ... lst = list(lst) * (not cancel) ... for i in lst: ... print(i) ... >>> process(range(3)) 0 1 2 >>> process(range(3), True) |
Ou même pire, saviez-vous que la déclaration d’héritage et les clauses d’exception pouvaient inclure une expression ? En rajoutant de l’unpacking, on obtient un truc bien marrant :
>>> class Parent: ... foo = "bar" ... >>> inherit = False >>> class Enfant(*[Parent] * inherit): ... pass ... >>> Enfant().foo Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Enfant' object has no attribute 'foo' >>> inherit = True >>> class Enfant(*[Parent] * inherit): ... pass ... >>> Enfant().foo 'bar' >>> catch = True >>> try: ... 42 / 0 ... except (ZeroDivisionError,) * catch: ... print("Nope") Nope >>> catch = False >>> try: ... 42 / 0 ... except (ZeroDivisionError,) * catch: ... print("Nope") Traceback (most recent call last): File "<ipython-input-12-c01f7e27284d>", line 2, in <module> 42 / 0 ZeroDivisionError: division by zero |
Évidelement ça marche avec n’importe quels entiers, mais où serait le fun ?
Et on peut utiliser un bool pour incrémenter une valeur.
>>> increment = True >>> value = 0 >>> for x in range(10): ... value += increment ... >>> value 10 >>> increment = False >>> for x in range(10): ... value += increment ... >>> value 10 |
Voilà de quoi bien vous marrer au boulot lors de votre prochaine code review !
Du Perlthon ! Ça fait froid dans le dos.
Le seul truc que je connaisse qui pouvait être utile là dedans c’est
('Valeur 1', 'Valeur 2')[True]
pour l’opérateur ternaire.Avant le
truc if condition else autre_truc
, on utilisait souventcondition and truc or autre_truc
. Seulement ça capote sitruc
s’évalue àFalse
:n’importe quoi les booléens en python, tout le monde sait qu’un booléen digne de ce nom doit pouvoir prendre au minimum 3 valeurs: True, False et ‘File_not_Found’
Ah ouais, très tordu !
C’est chouette de savoir qu’il y a moyen de faire du code très compliqué avec un langage très simple. Y a pas de raison qu’on soit obligé de faire du code clair
Ca ne marche pas, chez moi (invalid syntax, Python 2.7)
Testé avec Python 3, ça marche.
Alors, future imports, ou on utilise Python 3 chez S&M ?
Hum, ce serait ça (issu du What’s New in Python 3.0) ?
J’ai l’impression que ce n’est possible qu’avec Python 3.
J’ai du lancé python 3 sans le vouloir ^^^
@Yohann : seuls ceux qui lisent the DWTF peuvent comprendre cette vanne.
plus qu’à faire diagramme de
vannevenn alors.