Fonctions
En cours
Ce chapitre est en cours de construction. Il est déconseillé de s'y attaquer pour le moment.
A propos du chapitre
Objectif :
- Comprendre ce qu'est une fonction
- Déclarer et appeler une fonction
- Utiliser des fonctions pour structurer le code
- Réfléchir à la structure d'un problème
- Utiliser des fonctions écrites par d'autres
- Faire un dessin plus complexe avec moins de prise de tête:
TODO examples ici
Modalités :
- Programmation (Basthon)
- De la réflexion autour du code
Prérequis : "Programmation/Boucle for"
Difficulté : facile. Mais un peu perché tant qu'on a pas compris l'idée.
Introduction et magie
A la fin du précédent chapitre, j'avais dit :
Le code commence à devenir très compliqué à gérer, tellement que ça en devient critique.
Donc si on veut faire un dessin complexe, il nous faut un outils pour gérer la complexité.
C'est l'objet du prochain chapitre : fonctions.
Activité : trolling
Vérifiez que le titre du chapitre est bien "fonctions"
Solution
Ca y est, on y est ! Les F O N C T I O N S !!!!!
On va donc commencer par voir ce qu'est une fonction, puis s'entrainer un peu à les utiliser sur des programmes simples, et enfin comprendre comment on peut les utiliser pour structurer le code et faire des programmes complexes sans trop d'effort.
Fonction ?
Voici un petit programme qui dessine un rectangle paramétrisé sur sa position et ses dimensions :
from turtle import *
hauteur_rectangle = 100
largeur_rectangle = 200
position_x = 0
position_y = 0
penup()
goto(position_x, position_y)
pendown()
setheading(90) #on oriente la tortue vers le nord
forward(hauteur_rectangle)
right(90)
forward(largeur_rectangle)
right(90)
forward(hauteur_rectangle)
right(90)
forward(largeur_rectangle)
done()
Vous vous rappelez ? L'intérêt de paramétriser un programme, c'était de pouvoir le réutiliser facilement en changeant juste les paramètres...
Les fonctions permettent de faire ça au sein du même programme, en créant des sous-programmes paramétrisés !
Remarque
Les fonctions en programmation sont différentes des fonctions en mathématiques, même si elles ont beaucoup de similarités.
ce sujet est discuté plus en détail dans l'extension Lien avec les maths.
Réécrivons-donc le programme précédent avec une fonction :
from turtle import *
def dessiner_rectangle(x, y, largeur, hauteur):
penup()
goto(x, y)
pendown()
setheading(90) #on oriente la tortue vers le nord
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
dessiner_rectangle(0, 0, 200, 100)
done()
Activité : me faites pas trop confiance
Executez le programme ci-dessus pour vérifier qu'il fait bien ce qu'on attend.
Le code a été transformé comme ça :
La ligne avec def permet de donner un nom a la fonction, et de déclarer ses paramètres, on l'appelle le prototype:
Le bloc indenté contient les instructions de la fonction, son corps. Dans le corps de la fonction, les paramètres sont des variables :
penup()
goto(x, y)
pendown()
setheading(90) #on oriente la tortue vers le nord
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
Le prototype et le corps sont la définition de la fonction (d'où le def). Quand Python lit ces lignes, il enregistre la fonction, pour qu'on puisse l'executer plus tard, mais il ne l'exécute pas.
Pour exécuter la fonction, il faut l'appeler. Et comment on l'appelle ? Par son nom !
Et c'est pas une blague. On utilise le nom de la fonction, et on donne des valeurs pour ses paramètres, dans le même ordre que celui où on les a déclarés.
# nom fonction valeur1, v2, v3, v4
dessiner_rectangle(0, 0, 200, 100)
#def ... (x, y, largeur, hauteur):
Allez, quelques activités pour voir si tout est clair !
Activité : ALLO ?
Reprenez le code du programme avec la fonction :
from turtle import *
def dessiner_rectangle(x, y, largeur, hauteur):
penup()
goto(x, y)
pendown()
setheading(90) #on oriente la tortue vers le nord
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
dessiner_rectangle(0, 0, 200, 100)
done()
Et ajoutez un appel pour dessiner un second rectangle.
Solution
from turtle import *
def dessiner_rectangle(x, y, largeur, hauteur):
penup()
goto(x, y)
pendown()
setheading(90)
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
dessiner_rectangle(0, 0, 200, 100)
#ici, on rajoute un appel, avec des valeurs différentes.
dessiner_rectangle(0, 120, 100, 40)
done()
Activité : bodybuilding !
Ajoutez un corps à fonction dans le code suivant :
Activité : en entier
Dans un nouveau programme, écrivez et appelez une fonction qui dessine une forme de votre choix.
Valeur de retour
TODO implementer ici
Et voilà. Vous venez d'acquérir les bases des fonctions.
Vous ne l'avez pas encore remarqué, mais à mesure que vous progressez dans ce chapitre, votre aura augmente fortement.
C'est parce que les fonctions, quand elles sont bien utilisées, sont un outils qui permettent de dépasser certaines limites du cerveau humain !
Structurer le code : écoupage et abstraction
Imaginons que l'on veuille dessiner la maison de l'activité précédente :

C'est notre problème. Mais il est compliqué. Alors on peut le découper en un ensemble de sous-problèmes :
- Dessiner un mur
- Dessiner un toit
- Dessiner une porte
- Dessiner des fenêtres
Visuellement, ça donne ça :
On peut continuer le découpage pour chaque sous problème, et ainsi de suite. Par exemple, pour dessiner des fenetres.
Quand est-ce qu'on s'arrête ? Quand les problèmes semblent simples à résoudre.
TODO continuer ici, mais est-ce que c'est bon ?
abstraction (ancien)
Une fonction permet de séparer quoi du comment.
Activité : découpage
Activité : le jeu des différences
Voici une maison :

Et deux versions du code qui dessine la maison :
from turtle import *
speed(0)
largeur_maison = 100
hauteur_maison = 100
taille_toit = 140
penup()
goto(0, 0)
pendown()
setheading(90)
forward(hauteur_maison)
right(90)
forward(largeur_maison)
right(90)
forward(hauteur_maison)
right(90)
forward(largeur_maison)
penup()
goto((largeur_maison - taille_toit) / 2, hauteur_maison)
pendown()
setheading(0)
forward(taille_toit)
left(120)
forward(taille_toit)
left(120)
forward(taille_toit)
done()
from turtle import *
speed(0)
def dessiner_rectangle(x, y, largeur, hauteur):
penup()
goto(x, y)
pendown()
setheading(90)
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
def dessiner_triangle(x, y, taille):
penup()
goto(x, y)
pendown()
setheading(0)
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
largeur_maison = 100
hauteur_maison = 100
taille_toit = 140
dessiner_rectangle(0, 0, largeur_maison, hauteur_maison)
dessiner_triangle((largeur_maison - taille_toit) / 2, hauteur_maison, taille_toit)
done()
Dans chacune des deux versions du code, encadrez les lignes qui dessinent la maison avec des commentaires :
IMPORTANT
AVANT DE REGARDEZ LA SOLUTION, DISCUTEZ IMPERATIVEMENT DE VOTRE REPONSE AVEC VOTRE PROF. Ensuite, lisez attentivement la solution.
Solution
Je commence par vous donnez les deux encadrements, puis on en discute :
from turtle import *
speed(0)
# DE LÀ
largeur_maison = 100
hauteur_maison = 100
taille_toit = 140
penup()
goto(0, 0)
pendown()
setheading(90)
forward(hauteur_maison)
right(90)
forward(largeur_maison)
right(90)
forward(hauteur_maison)
right(90)
forward(largeur_maison)
penup()
goto((largeur_maison - taille_toit) / 2, hauteur_maison)
pendown()
setheading(0)
forward(taille_toit)
left(120)
forward(taille_toit)
left(120)
forward(taille_toit)
# A DE LÀ
done()
from turtle import *
speed(0)
def dessiner_rectangle(x, y, largeur, hauteur):
penup()
goto(x, y)
pendown()
setheading(90)
forward(hauteur)
right(90)
forward(largeur)
right(90)
forward(hauteur)
right(90)
forward(largeur)
def dessiner_triangle(x, y, taille):
penup()
goto(x, y)
pendown()
setheading(0)
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
# DE LÀ
largeur_maison = 100
hauteur_maison = 100
taille_toit = 140
dessiner_rectangle(0, 0, largeur_maison, hauteur_maison)
dessiner_triangle((largeur_maison - taille_toit) / 2, hauteur_maison, taille_toit)
# À DE LÀ
done()
Vous avez sans doute remarqué, avec étonnement, que les fonctions dessiner_triangle et dessiner_rectangle ne sont pas incluses dans le code de la maison. C'est une histoire de point de vue.
Un appel de fonction, comme :
TODO revoir l'activité ci dessus et faire mieux
Peut-être montrer un arbre de sous-problèmes, et expliquer qu'une fonction permet de "couper" les branches. ?
reprendre du début avec cet exemple ??
ptet leur faire construire un programme en mode "appel d'abord" ?
ouais franchement des arbres de problème proche du code ??
Partage
NE PAS OUBLIER DE PARLER DE VALEUR DE RETOUR
INDEPENDANCE DES APPELS