Le zen Python

Oui. Même quand on est tout seul, il est important d’être simple et clair, lisible, concis. Parce que déjà, qui dit simplicité dit rapidité. Ensuite parce que si vous revenez plusieurs jours après sur tel ou tel travail, eh bien, « je » est un autre ! « Mais comment ça marche, çà ? Qu'est-ce que j'ai voulu faire, là ? »

Les maîtres en langages informatiques parlent parfois de « philosophie ». Je trouve le mot un peu trop fort ! Cependant, « morale » n’est pas idiot. En effet, la morale est la science des mœurs, des comportements en sociétés. Et le développement informatique est le plus souvent affaire d’équipe. Ce que l’on a écrit, autrui doit le lire et le comprendre facilement. Réciproquement, vous serez reconnaissant à la personne qui a écrit le programme sur lequel vous devez travailler, si son texte est clair, si sa logique est visible. De ce point de vue, textes littéraire et informatique sont bien apparentés. Le lecteur que je suis apprécie la simplicité, la clarté. La technicité du discours de Jankélévitch le rend imbuvable. La concision, la pureté de Montaigne, de Camus, de Cyrulnyk, en font des écrivains. Et des philosophes. La déontologie du métier devrait être en premier lieu de s’adresser aux hommes, pas aux agrégés (désagrégés, en fait). Ce n’est pas un hasard si les trois auteurs que j’ai cités sont des philosophes du courage : il faut être courageux pour être simple. Ne pas enrober. Fuir l’euphémisme et la litote. Faire court. L’hypercorrection du potache est un symptôme de cette lâcheté : remplir, pour masquer la vacuité. Tirer à la ligne. Quand on n’a rien d’autre à faire que d’aller à la recherche du temps perdu, là, on va y tirer, à la ligne !

Un programme est une machine, complexe. Et son fonctionnement ne doit pas être mystérieux. C’est quand même chié, non ? Pareil qu’une pensée ! Et toujours pour filer la métaphore, aussi bien dans la maintenance d’un logiciel qui va s’étendre sur plusieurs années, décades même, que dans l’avenir des vraies idées, dans la construction du vrai progrès, qui s’étendent sur des siècles, chaque pensée est une étape dans une grande intertextualité. Les questions de la Boétie, de Maud au cimetière d’Arlington, de Camus, de Brassens devant le champ d'honneur, eh bien, on est toujours et de nouveau en train de se pencher dessus. Mais sans la douleur du geek qui s’arrache les tifs parce qu’il ne comprend pas ce que le collègue a voulu faire là. Avec joie et larmes. De tristesse, pas de douleur. « Tout ce à quoi vous avez consenti. » Mais oui, je pleure, là.

Zoom arrière

Enfin bref. Je disais. Être lisible. Même quand on est tout seul sur le projet ! (Comme votre serviteur qui s’est attelé au treizième travail d’Hercule, un logiciel de jeu pédagogique en réseau pour les maths, l’orthographe et la grammaire. Peut-être ne serai-je pas toujours tout seul dessus, menfin, pour l’instant, c’est le cas. Et l’outil qui permettra d’apprendre tout seul, à tout âge, chez soi, en rigolant, ne sera pas pondu tout de suite.)

Oui. Même quand on est tout seul, il est important d’être simple et clair, lisible, concis. Parce que déjà, qui dit simplicité dit rapidité. Ensuite parce que si vous revenez plusieurs jours après sur tel ou tel travail, eh bien, « je » est un autre ! « Mais comment ça marche, çà ? Qu'est-ce que j'ai voulu faire, là ? »

3w74rvpac2911

Après avoir longuement caboté entre Basic, Pascal, C, les langages « du web » (HTML, CSS, PHP),

je suis arrivé chez Python

Et j’ai posé mon sac à dos.
En conclusion d’un des cours sur Python à Open Classrooms, j’ai trouvé la « PEP 20 », sur laquelle le prof attire l’attention, et qu’il a traduite. C’est ce qu’on appelle le zen Python. Je vous communique ça. Vous y retrouverez peut-être le parallèle que j’ai fait avec la littérature et la philosophie. À part en un ou deux points. On peut en discuter.

PEP 20: Python Enhancement Proposal (propositions d'amélioration de Python)

Beautiful is better than ugly (le beau est préférable au laid)

Explicit is better than implicit (l'explicite est préférable à l'implicite )

Simple is better than complex (le simple est préférable au complexe)

Complex is better than complicated (le complexe est préférable au compliqué)

Flat is better than nested (le plat est préférable à l'imbriqué) —  Moins littéralement, du code trop imbriqué (par exemple une boucle imbriquée dans une boucle imbriquée dans une boucle…) est plus difficile à lire.

Sparse is better than dense (l'aéré est préférable au compact)

Readability counts (la lisibilité compte)

Special cases aren't special enough to break the rules (les cas particuliers ne sont pas suffisamment particuliers pour casser la règle)

Although practicality beats purity (même si l'aspect pratique doit prendre le pas sur la pureté) — Moins littéralement, il est difficile de faire un code à la fois fonctionnel et « pur ».

Errors should never pass silently (les erreurs ne devraient jamais passer silencieusement)

Unless explicitly silenced (à moins qu'elles n'aient été explicitement réduites au silence)

In the face of ambiguity, refuse the temptation to guess (en cas d'ambiguïté, résistez à la tentation de deviner)

There should be one — and preferably only one — obvious way to do it (il devrait exister une — et de préférence une seule — manière évidente de procéder)

Although that way may not be obvious at first unless you're Dutch (même si cette manière n'est pas forcément évidente au premier abord, à moins que vous ne soyez Néerlandais)  —  il faudrait peut-être indiquer que c'est une blague ?

Now is better than never (maintenant est préférable à jamais)

Although never is often better than *right* now (mais jamais est parfois préférable à immédiatement)

If the implementation is hard to explain, it's a bad idea (si la mise en œuvre est difficile à expliquer, c'est une mauvaise idée)

If the implementation is easy to explain, it may be a good idea (si la mise en œuvre est facile à expliquer, ce peut être une bonne idée)

Namespaces are one honking great idea -- let's do more of those (les espaces de noms sont une très bonne idée — faisons-en plus !—

 

you-have-python
Ma phase d’apprentissage est à présent à peu près close. Ce qui m’a le plus occupé, c’est que ma formation était à base de « programme texte », alors qu’aujourd’hui, les logiciels sont « pilotés par les événements ». Surtout pour cause d’interface graphique. Mais j’y suis arrivé, et maintenant, je sais à peu près tout faire. J’avais une bonne algorithmique, j’ai ajouté une connaissance des objets d’interface. J’ai une aide : internet ! C’est pas de la mise en abîme, ça ? La documentation en ligne, parfois en bon français, parfois en anglais, Wikipédia, Open Classrooms, divers forums, y a pas, on peut vraiment apprendre tout seul.

Je viens de parler d’algorithme. Un algorithme, ce n’est pas ce qu’un collégien ou un lycéen français peut croire à la sortie des chapitres de maths qui en traitent, et qui sont pitoyables. Le mot est d’abord mathématique. C’est une suite d’opérations diverses, variables et répétées, qui conduisent à un résultat de façon certaine. On en découvre un en cours moyen avec la division euclidienne d’un entier (dividende) par un autre (diviseur). Il faut trouver le quotient et le reste.

Partir de la gauche du dividende
Prendre assez de chiffres pour que le nombre ainsi constitué soit plus grand que le diviseur.
Nommons « apartager » ce nombre
Tant que tout le dividende n’est pas partagé :
        poser la question « combien de fois le diviseur dans àpartager ? »
        nommons q la réponse à cette question
        inscrire q sous le diviseur #c’est le début du quotient#
        calculer le produit p de q par le diviseur
        soustraire p de apartager.
        attribuer le nom « apartager » au résultat de cette soustraction.
Et rebelote !


Tout ce qui est indenté, est à recommencer tant que c’est pas fini.

Certains confondent ceci avec l’algorithme d’Euclide ! Pas de bol. L’algorithme de la division euclidienne n’est pas celui qu’on appelle algorithme d’Euclide, et qui lui, sert à autre chose : trouver le PGCD (plus grand commun diviseur) de deux nombres.

On aborde ça au collège, ou au lycée, ça dépend du ministre. L’idée mathématique qui autorise l’algorithme d’Euclide, le plus rapide pour trouver un pgcd, est la suivante : un diviseur commun à deux nombres est forcément commun aussi à leur différence.
Cela s’écrit : pgcd(a, b) = pgcd (b, a - b) (en supposant a plus grand que b).
Et cela va plus loin : on peut retirer plusieurs fois b de a : pgcd(a, b) = pgcd (b, a - n x b)
Le deuxième nombre est le reste dans la division euclidienne de a par b. On comprend maintenant pourquoi c’est Euclidien !  a = b x n + r. Au lieu de s'appeler « q » , ici le quotient est « n » .

Ça mène  au résultat, parce que ça remplace un problème par un problème identique, mais avec des nombres plus petits : b et a - n x b. On va en effet recommencer jusqu’à ce qu’un des nombres soit multiple de l’autre, c’est-à-dire jusqu’à ce que l’on trouve un reste égal à zéro. Le pgcd sera le dernier diviseur.

Voilà deux exemples de vrais algorithmes. Un troisième, très intéressant, plus à l’usage du lycée, mais tout-à-fait abordable au collège, est celui de la recherche de la valeur approchée de la solution d’une équation par dichotomie. Il fera l’objet d’un article à part, les notions mathématiques qui le justifient étant plus complexes (première-terminale).

Pour en revenir à la philosophie Python, qui parle de beauté du texte, voici cet algorithme d’Euclide, implémenté en langage C, puis en Python. (Langage plus rapide à écrire, car moins grumeleux).

___________________________C________________________

#include <iostream>
#include <string>
#include "math.h"
using namespace std;

int pgcd(int a, int b)
{
      int mini(0), maxi(0), q(0), r(1);
      while (r!=0)
      {
            mini = min(a,b);
            maxi = max(a,b);
            q = maxi / mini;
            r = maxi % mini;
            a = mini;
            b = r;
      }
return mini;
}

int main()
{
      int premierNombre, deuxiemeNombre;
      char encore('o');
      while(encore=='o')
      {
            cout << "premier nombre ? ";
            cin >> premierNombre;
            cout << " deuxième nombre ? ";
            cin >> deuxiemeNombre;
            cout << "Le PGCD de "<<premierNombre<<" et "<<deuxiemeNombre<<" est :"
                                    <<pgcd(premierNombre, deuxiemeNombre,compteur) << endl;
            cout << "encore ? " << endl;
            cin >> encore;
      }
return 0;
}

___________________________Python________________________
def pgcd(a, b) :
      r = 1
      while r != 0 :
             mini = min(a, b)
             maxi = max(a, b)
             q = maxi // mini
             r = maxi % mini
             a = mini
             b = r
      return mini

encore = 'o'
while encore == 'o' :
      premier_nombre = input("Premier nombre ?")
      deuxieme_nombre = input("Deuxième nombre ?")
      print("Le PGCD de ", premier_nombre, " et de ", deuxieme_nombre,
                  " est ", str(pgcd(int(premier_nombre), int(deuxieme_nombre))))
      encore = input("encore ? »)

Les deux langages sont assez proches, car l’un, Python, est inspiré de C.


Aussi bien en C qu’en Python :

1) « while » signifie le « tant que » que vous voyez dans l’algorithme.
2) Il y a deux signes « = » :
Le « = »  simple,  justement, n’est pas du tout le nôtre. Il signifie une affectation.
Par exemple, « a = mini » signifie que l’on met dans l’emplacement mémoire réservé à la variable « a » le contenu de la variable « mini ».
Mais « == » est le vrai signe égal. Il sert pour les « tests ». « while encore == ‘o’ » signifie : tant que la valeur reçue au clavier est le caractère ‘o’. (c’est très sommaire, comme réception d’une saisie au clavier).
3) L’indentation signifie que les instructions indentées sont effectuées sous certaines conditions, ou bien répétées. Elles font suite par exemple à un while. Elles sont conseillées en C, et obligatoires en Python. Ce qui permet de ne pas avoir à taper ces accolades du C. Il faut en effet que le logiciel qui va lire le programme pour l’interpréter ou le compiler, comprenne que les six instructions qui suivent le while sont concernées. Cette signifiance passe en C par les accolades, en Python par l’indentation. D’où une rapidité accrue en Python, pas d’accolades à taper. Juste un deux points.
4) La programmation est structurée avec une fonction principale, main, en C, ou un programme principal en Python, qui n’est pas déclaré en tant que tel, et une fonction pgcd() appelée par le programme principal.
5) min() et max() sont les mêmes fonctions en C et Python, elles renvoient respectivement le plus petit et le plus grand des nombres qu’on lui donne en arguments. Petite différence : elles sont « natives » en Python (présente sans qu’il soit besoin d’inclure une bibliothèque), tandis qu’en C, il faut inclure « math.h », voyez tout en haut du programme.
6) « / »  et « % » sont le quotient et le reste entier. Nuance entre C et Python : en Python, « / » provoque la division « réelle », avec un quotient à virgule. Il faut « // » pour avoir la division entière.

Ce qui diffère vraiment :

« int » signifie « integer », c’est à dire « entier ».
En C, il sert à déclarer le type de la variable, ou de la valeur de retour d’une fonction. De la même façon, « char » signifie « caractère » (une lettre, un chiffre, une ponctuation, etc.)

En Python, « int () » est une fonction, qui transforme en nombre entier ce qui peut l’être (par exemple, une chaine de caractère du type « 345 », ou alors un nombre de type « à virgule », mais du type 4.0, qui est donc entier. De la même façon, « str() » est une fonction qui transforme un nombre en chaine de caractères (string). 

Le type des variables est une notion informatique qui correspond au fait qu’on ne code pas de la même façon les nombres entiers, les « décimaux », et les chaines de caractères.

Le « typage « en C est statique, ce qui veut dire qu’on doit déclarer chaque variable et son type. Il peut s’accompagner d’une initialisation : « int mini(0) » signifie qu’on déclare une variable nommée « mini », entière, et qu’on lui donne la valeur zéro, pour commencer.
Le typage en Python est dynamique : la variable prend son type à sa première affectation. « mini = min(a,b) » signifiera que mini est entière, parce que la valeur qu’elle recevra sera entière.


En Python, « input() » sert à recevoir une valeur saisie au clavier, et permet de proposer un message d'invite.
En C, « cout » et « cin » (lire c-out et c-in) sont, l’affichage d’un message à l’écran, et la réception d’une saisie clavier de l’utilisateur.

Enfin, de la même façon que l'indentation, signifiante en Python, remplace les accolades du C, le fait d'aller à la ligne signifie une nouvelle instruction, et remplace les point-virgule du C. En Python, on met une instruction par ligne, ce qui contribue encore à la lisibilité. Ceci est conseillé en C, un bon programmeur C évite de mettre plusieurs instructions sur une seule ligne. Moralité : en Python, pour la même disposition du texte, on n'a pas à écrire toutes ces accolades et point-virgule.

Le Club est l'espace de libre expression des abonnés de Mediapart. Ses contenus n'engagent pas la rédaction.