A) Introduction
Est-il raisonnable de croire que des élèves habitués aux instructions de saisie et d’affichage avec Scratch au collège vont pouvoir, en classe de seconde, s’adapter sans difficulté en les remplaçant par des fonctions Python ?
Personnellement, je ne le pense pas, à moins d’expliquer les notations Python en termes d’entrées-sorties :
- les entrées sont ajoutées dans une instruction « def nom_algorithme(...) », en les séparant par des virgules.
- les sorties sont ajoutées dans une instruction « return ... », en les séparant par des virgules.
- l’algorithme est testé dans la console Python en entrant les valeurs de test dans une instruction « nom_algorithme(...) ».
J’ai automatisé cette démarche en adaptant le logiciel SofusPy où j’ai introduit des blocs « Entrée » et « Sortie », auxquels on peut donner une interprétation « collège » (saisie et affichage) ou « lycée » (paramètre d’une fonction et instruction de retour) grâce à une liste déroulante.
Pour illustrer l’article, je m’inspirerai notamment de deux activités pédagogiques (avec corrigés) proposées par Claire Savinas sur le site web de la calculatrice NumWorks (lien) : je les trouve non seulement pertinentes mais aussi, comme j’exerce en IUT, j’éviterai ainsi le risque de proposer des exemples ne correspondant pas suffisamment aux attentes de mes collègues de lycée par méconnaissance des « réalités de terrain ». En outre, il s’avère que l’approche entrées-sorties est clairement revendiquée dans la fiche « Premiers pas en Python » :
Je terminerai en reprenant, sous le prisme de la programmation par blocs, plusieurs problèmes traités en Python par Benjamin Clerc dans un article du N° 65 intitulé « Les algorithmes du programme 2019 de mathématiques de Seconde ».
B) Exemple 1 : maximum de nombres
Dans la fiche d’activités « Fonctions imbriquées et à plusieurs arguments », Claire Savinas commence par créer une fonction calculant le maximum de 2 nombres, avant de la réutiliser pour calculer le maximum de plusieurs nombres (3, 4 et 8). Voici quelques programmes extraits du corrigé :
Je suis d’autant plus réceptif à cette progression pédagogique que je la propose depuis des années à mes étudiants d’IUT, afin de leur montrer l’intérêt du découpage en sous-programmes. A la fin, je la prolonge pour aboutir à la résolution de ce problème dans un module d’initiation à l’algorithmique :
Dans un concours de saut à skis, chaque skieur est noté par 5 juges. Sa note finale est obtenue en sommant les 5 notes, puis en soustrayant à cette somme la note minimale et la note maximale.
La programmation par blocs a la réputation d’être souvent chronophage, ce qui est plutôt le cas ici si on introduit une fonction dans le programme Blockly :
Mais en utilisant des blocs d’entrées-sorties, ainsi que des blocs à syntaxe libre (ici pour le test « a>b »), cela devient une approche très efficace pour obtenir rapidement le code Python.
Pour obtenir directement le code Python souhaité, il est possible de combiner l’utilisation de blocs d’entrées-sorties avec celle d’une fonction Blockly :
L’introduction de la fonction Blockly peut être évitée, à condition de procéder en deux étapes :
- dans un premier temps, on modifie le code Python de l’exercice précédent (maximum de deux nombres) en remplaçant « def algo » par « def maximum ».
- dans un second temps, on effectue une programmation par blocs afin de compléter le code Python précédemment obtenu à l’étape 1 ; après l’avoir réalisée, il reste à positionner le curseur en bas de l’éditeur Python, puis à cliquer sur le bouton « insérer blocs »
C) Exemple 2 : intérêts composés
Dans la fiche d’activités « Découverte de la boucle while », Claire Savinas met en évidence les points communs ainsi que les différences entre cette boucle et la boucle « for ». Voici le contexte de l’exercice :
Robin a maintenant 18 ans et souhaite s’acheter une voiture avec un budget de 2 000 euros. Il dispose de 1 500 euros sur un compte avec un taux d’intérêt de 2,5 % par an. Le montant des intérêts est calculé sur le montant disponible sur le compte à la date d’anniversaire du propriétaire du compte et est déposé sur celui-ci le même jour. On suppose qu’il n’effectue ni nouveau dépôt ni retrait.
Dans les diverses questions de l’activité, plusieurs programmes sont fournis, parmi lesquels :
Le programme de gauche, après correction de l’indentation du return, permet de connaître la somme disponible n années après le dépôt initial de 1500 euros à l’aide d’une boucle « for ». Le programme de droite calcule les intérêts composés à l’aide d’une boucle « while », afin de déterminer combien d’années il faudra à Robin pour pouvoir s’acheter une voiture valant 2000 euros.
Outre des objectifs algorithmiques sur les boucles, l’activité Python vise aussi à montrer comment procéder lorsqu’un algorithme a deux sorties. Cela me conduira donc à illustrer l’utilisation de la programmation par blocs dans un contexte multi-sorties.
Si les élèves n’ont pas accès à un ordinateur pendant une séance, ce qui est généralement le cas, la simple projection du programme Blockly au tableau peut servir de point de départ à une activité Python avec leur calculatrice : il constitue en effet un algorithme à coder en Python, dont les notations sont à la fois intuitives et suffisamment éloignées du code Python final pour ne pas trop « mâcher le travail » des élèves, que ce soit en informatique mais aussi en mathématiques (augmentation de 2.5%)...
D) Exemple 3 : équation du second degré
Les nouvelles préconisations du lycée (utilisation systématique de fonctions) ont transformé un banal exercice de codage sur les instructions conditionnelles en un casse-tête : en effet, quel type d’information doit renvoyer la fonction correspondante, sachant qu’il peut y avoir 0, 1 ou 2 solution(s) ?
Formellement, on peut dire que la fonction renvoie une liste (ou un ensemble) à 0, 1 ou 2 élément(s). Mais il est loin d’être certain que cela soit judicieux pédagogiquement, car on complexifie alors un banal exercice sur les instructions conditionnelles.
Personnellement, à moins de prolonger l’exercice par une réutilisation des solutions de l’équation du second degré, j’ai du mal à comprendre pourquoi il ne faudrait plus passer par l’affichage des résultats : en effet, les « print » font aussi partie de la pensée informatique, comme le rappelle Sébastien Hoarau dans un article intitulé « print ou return ? les deux bien sûr ! » (voir lien).
Si j’enseignais au lycée, il est probable que je privilégierais cette solution Python avec des « return hétéroclites » (nombre, tuple et texte), parce qu’elle ne nécessite aucune explication technique (notations naturelles sur la forme). Et s’il n’y avait pas eu la préconisation du « return », j’aurais mis des « print » (deux « print » quand il y a deux solutions).
Pour ma part, j’ai toujours traité cet exemple avec des affichages dans mon module d’initiation à l’algorithmique, parce qu’il m’aurait sinon fallu introduire formellement les listes de façon prématurée. En outre, j’ai longtemps enseigné des langages de programmation où l’utilisation de listes et de fonctions était beaucoup moins facile à mettre en oeuvre qu’avec Python.
Dans un article du N°66 intitulé « Les exemples d’algorithmes du nouveau lycée général, en Python », Alain Busser définit une fonction « racine », puis l’utilise pour résoudre une équation du second degré en stockant les solutions dans un ensemble. Pour justifier son approche mathématiquement, il explique ceci :
Résoudre une équation, c’est donner l’ensemble de ses solutions. Il est donc logique de définir une fonction qui, aux réels a, b, et c, associe l’ensemble des solutions de l’équation a×x²+b×x+c=0.
Dans le code Python associé, le cas « delta=0 » peut être regroupé avec le cas « delta>0 », à cause de la propriété d’unicité des éléments : la méthode « add » n’ajoute pas un élément s’il est déjà présent dans l’ensemble (type « set »).
Blockly ne gérant pas les ensembles, il n’est pas possible d’obtenir le programme Python d’Alain Busser à partir de blocs. Une alternative est de créer une liste, qu’on complète avec l’ajout des solutions, avant de la transformer en un ensemble dans l’instruction de sortie :
Le code produit est exécutable dans SofusPy, son interpréteur Python (Skulpt) prenant en charge les ensembles. On peut vérifier qu’une racine double (delta=0) n’apparaît alors qu’une fois quand on affiche l’ensemble.
Si on ne réutilise pas les solutions d’une équation du second degré, il peut sembler vain aux élèves d’introduire une liste (ou un ensemble). C’est pourquoi je prolonge l’exercice par la résolution d’une équation bicarrée, ce qui conduira à parcourir la liste des solutions de l’équation du second degré pour en prendre leur racine carrée et son opposé. Voici un code Python que j’ai obtenu à partir de blocs avec SofusPy :
Et voici le programme Blockly initial :
Ce programme Blockly est donné à titre indicatif, parce que l’exemple n’est pas très représentatif de l’intérêt pratique de la programmation par blocs au lycée.
E) Exemple 4 : droites
Dans son article du N° 65 intitulé « Les algorithmes du programme 2019 de mathématiques de Seconde », Benjamin Clerc a recherché dans le programme officiel de Seconde des « indications au sujet des algorithmes que l’on peut y mettre en œuvre » . Cela l’a conduit à présenter 14 problèmes mathématiques dont il donne une solution en Python.
J’en détaillerai deux, dont le thème porte sur les droites : alignement de 3 points et équation cartésienne. Pour les autres, je renvoie les lecteurs intéressés vers ce lien qui permet de les consulter et de les tester en ligne.
B. Clerc propose une solution où les paramètres sont des tuples de longueur 2 :
def EQ_DROITE(A,B):
x_A,y_A=A
x_B,y_B=B
if x_A==x_B:
if y_A==y_B:
droite="Points identiques !"
else:
droite="Droite verticale d'équation x = "+str(x_A)+"."
elif y_A==y_B:
droite="Droite horizontale d'équation y = "+str(y_A)+"."
else:
m=(y_B-y_A)/(x_B-x_A)
p=y_A-m*x_A
droite="Droite oblique d'équation y = "+str(m)+"x + "+str(p)+"."
return droite
Télécharger
L’abscisse et l’ordonnée sont récupérés à l’aide d’une affectation multiple, qu’il faut remplacer par deux affectations simples avec Blockly pour conserver des tuples de longueur 2 :
Comme cet artifice ne me satisfait guère pédagogiquement, j’abandonnerai les tuples :
Voici le code Python produit par SofusPy :
def algo(x_A,y_A,x_B,y_B) :
if x_A == x_B:
if y_A == y_B:
droite = 'points identiques !'
else:
droite = 'x =' + str(x_A)
elif y_A == y_B:
droite = 'y =' + str(y_A)
else:
m = (y_B-y_A)/(x_B-x_A)
p = y_A-m*x_A
droite = 'y =' + str(m) + 'x + ' + str(p)
return droite
# print car pas de console Python dans SofusPy
print(algo(2,3,-1,-9))
Télécharger
B. Clerc propose une solution où les paramètres sont des tuples de longueur 3 (nom du point, abscisse et ordonnée) :
def pts_alignes(A,B,C):
pt_1,x_A,y_A=A
pt_2,x_B,y_B=B
pt_3,x_C,y_C=C
if x_A==x_B:
if x_A==x_C:
message="droite verticale d'équation x = "+str(x_A)+"."
else:
message=pt_1+", "+pt_2+" et "+pt_3+" ne sont pas alignés."
elif y_A==y_B and y_A==y_C:
message="droite horizontale d'équation y = "+str(y_A)+"."
else:
if x_A==x_C:
#permet d'éviter la division par 0 dans le calcul de m2
message=pt_1+", "+pt_2+" et "+pt_3+" ne sont pas alignés."
else:
m1=(y_B-y_A)/(x_B-x_A)
m2=(y_C-y_A)/(x_C-x_A)
if m1==m2:
p=y_A-m1*x_A
message="droite oblique d'équation y = "+str(m1)+"x +"+str(p)+"."
else:
message=pt_1+", "+pt_2+" et "+pt_3+" ne sont pas alignés."
return message
Télécharger
Il me semble souhaitable d’élaguer l’arborescence d’instructions conditionnelles :
def algo(x_A,y_A,x_B,y_B,x_C,y_C) :
message = 'les 3 points ne sont pas pas alignés'
if x_A == x_B and x_A == x_C:
message = 'x =' + str(x_A)
elif y_A == y_B and y_A == y_C:
message = 'y =' + str(y_A)
elif x_A != x_B and x_A != x_C:
m1 = (y_B-y_A)/(x_B-x_A)
m2 = (y_C-y_A)/(x_C-x_A)
if (round(m1,10)) == (round(m2,10)):
p = y_A-m1*x_A
message = 'y =' + str(m1) + 'x + ' + str(p)
return message
Télécharger
Par défaut, on suppose que les points ne sont pas alignés dans le message initial, avant d’examiner les trois alignements possibles (droite verticale, droite horizontale et droite oblique), ce dernier cas étant testé par l’égalité à arrondi près des pentes des droites AB et AC. Le programme Python ci-dessus résulte de la traduction par SofusPy de ce programme par blocs :
Si on veut gagner du temps, il est probablement préférable de n’écrire que partiellement ce programme par blocs, sans compléter toutes les instructions conditionnelles, et de finir le travail dans l’éditeur Python.
F) Conclusion
La programmation par blocs peut faciliter l’enseignement de Python au lycée, que ce soit d’un point de vue méthodologique ou d’un point de vue opérationnel.
D’un point de vue méthodologique, l’introduction de blocs d’entrée et de sorties permet d’illustrer une approche classique de l’algorithmique : à partir d’entrées, un algorithme produit des sorties. Cela vaut non seulement pour les anciens programmes de lycée et ceux de collèges (entrée=saisie, sortie=affichage), mais aussi pour les nouveaux programmes de lycée (entrée=paramètre de fonction, sortie=valeur renvoyée).
D’un point de vue opérationnel, ces blocs d’entrée et de sortie contribuent grandement à l’obtention rapide de codes Python conformes aux nouvelles préconisations au lycée (introduction systématique de fonctions). Je l’ai illustré en produisant ainsi divers programmes Python émanant d’enseignants de lycée formateurs académiques.
Si les élèves n’ont pas accès à un ordinateur pendant une séance, ce qui est généralement le cas, la simple projection du programme Blockly au tableau peut servir de point de départ à une activité Python avec leur calculatrice : il constitue en effet un algorithme très lisible à coder.
SofusPy ne nécessite aucune installation particulière puisque le logiciel est disponible en ligne sur mes pages professionnelles consacrées à Blockly (lien) et celles de l’IREM de la Réunion (lien).
Rq : le site de l’IREM n’a pas encore été mis à jour pour les blocs d’entrée et de sortie.