Les fonctions en Python
Attention
Ce chapitre présente une notion très importante. Prenez bien votre temps pour comprendre, et n'hésitez pas à poser des questions !
Les logiciels font partie des "objets" les plus complexes jamais conçus par des humains.
Il nous est impossible de visualiser mentalement un logiciel de grande taille, ou même de taille moyenne dans tous les détails de son fonctionnement à la fois.
Voici un aperçu du nombre de lignes (approximatifs) de code (sloc) de certains logiciels1. Les commentaires sont exclus.
| Logiciel | Usage | Ordre de grandeur sloc | Principaux langages |
|---|---|---|---|
| OpenFlappyBird | Une version Libre de Flappy Bird | 600 | Java |
| SuperTux | Une version Libre de Super Mario | 100K | C++ |
| Terasology | Une version Libre de Minecraft | 130K | Java |
| KDenLive | Editeur vidéo non-linéaire | 150K | C++, C |
| Audacity | Enregistrement et traitement audio | 1M | Python, C, C++ |
| CPython | Interpréteur Python le plus répandu | 1.5M | Python, C |
| Blender | Modélisation 3D | 2.3M | C++, C, Python |
| llvm | Suite de compilation pour les langages de la famille du C. | 11M | C++, C, Python, LLVM IR, ASM, CMake2, Objective C |
| Firefox | Navigateur Web | 25M | C++, C, Python, JavaScript, ASM, Rust |
A titre de comparaison, l'intégrale du Seigneur des Anneaux compte environ 400 000 mots3.
Pour surpasser cette complexité, les langages de programmation fournissent des outils comme les fonctions.
Pour découvrir les fonctions on va créer dans ce chapitre un programme qui fait un dessin à l'aide de Turtle.
Turtle
Turtle est un outils de Python qui permet de dessiner à l'écran.
Pour l'utiliser, il suffit d'ajouter
Ensuite, vous pouvez simplement utiliser Turtle, par exemple avec ce programme :
Copiez-collez le dans un fichier Python et lancez-le. Vous devriez voir apparaître une fenêtre avec un dessin du style :

Erreurs
Il se peut que votre ordinateur ne soit pas bien configuré et que le programme ne marche pas.
Dans ce cas, vous pouvez utiliser Basthon pour ce chapitre.
Diriger la tortue, P1
Pour dessiner avec Turtle, on dirige une tortue graphique. C'est un peu comme un stylo.
Voici un exemple de programme :
from turtle import *
# on avance de 100
forward(100)
# on tourne de 120 degrés vers la gauche
left(120)
forward(100)
left(120)
forward(100)
#on dit a Python qu'on a fini.
done()
Activité
Colorier
On peut changer la couleur du trait avec
Ou COULEUR est le nom d'une couleur :
TODO liste exhaustive couleurs et le rendu
Activité
Vous pouvez aussi colorier l'intérieur des formes que vous dessinez :
- Utilisez
fillcolor(COULEUR)pour choisir une couleur de remplissage - Utilisez
begin_fill()pour avant de dessiner la forme - Utilisez
end_fill()après avoir dessiné la forme.
Activité
Diriger la tortue, P2
Au départ la tortue est en (0, 0). On peut la faire aller à une position (X, Y) donnée en faisant :
Où X et Y sont les coordonnées.
Activité
Déplacez le carré vers le haut gauche de l'écran.
Utilisez goto.
Vous avez sans doute remarqué que la tortue fait un trait quand elle se déplace.
On peut ne pas dessiner durant un déplacement de la tortue en utilisant
avant le déplacement. Pour recommencer à dessiner, il faut utiliser
Activité
On complique
Les carrés c'est pas très drôle. Essayons de dessiner un truc un peu plus sympa.
Activité : maison
Dessinez une maison, comme ça :

Le toit a la couleur "brown" et les murs la couleur "red".
Remarque : vous pouvez orienter la tortue dans un angle donné en utilisant
Par exemple
Essayez eventuellement de structurer votre code en blocs et de le préciser avec des commentaires.
Faites de l'essai erreur : dessinez les formes puis deplacez-les.
from turtle import *
#Un carré pour les murs
penup()
goto(0, 0)
pendown()
pencolor("red")
fillcolor("red")
begin_fill()
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
end_fill()
# Un triangle pour le toit
penup()
goto(-125, 100)
pendown()
pencolor("brown")
fillcolor("brown")
begin_fill()
forward(150)
left(120)
forward(150)
left(120)
forward(150)
end_fill()
done()
Quelle jolie maison ! Mais c'est un peu... sombre à l'intérieur, et on peut pas y rentrer. Il faut ajouter une porte et une fenêtre ... Allez hop, activité !
Activité : menuiseries
Essayez d'ajouter une porte et une fenêtre à la maison, comme ça :

la couleur de la porte est "brown" et la couleur de la fenêtre est "white".
Essayez sérieusement pendant 15 ou 20 minutes. Notez les difficultés que vous rencontrez. Si au bout de 20 minutes vous n'y arrivez toujours pas, appelez votre prof.
Soyez méthodiques et séparez bien votre code en morceaux.
from turtle import *
#Un carré pour les murs
penup()
goto(0, 0)
pendown()
pencolor("red")
fillcolor("red")
begin_fill()
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
end_fill()
# un carré pour la porte
penup()
goto(-60, 0)
pendown()
pencolor("brown")
fillcolor("brown")
begin_fill()
setheading(270) #petit ajustement de l'orientation de la tortue
left(90)
forward(30)
left(90)
forward(60)
left(90)
forward(30)
left(90)
forward(60)
end_fill()
# Un triangle pour le toit
penup()
goto(-125, 100)
pendown()
pencolor("brown")
fillcolor("brown")
begin_fill()
setheading(0) #petit ajustement de l'orientation de la tortue
forward(150)
left(120)
forward(150)
left(120)
forward(150)
end_fill()
# Un triangle pour la fenêtre
penup()
goto(-50, 175)
pendown()
pencolor("white")
fillcolor("white")
begin_fill()
forward(60)
left(120)
forward(60)
left(120)
forward(60)
end_fill()
done()
Un tour de magie
Normalement, vous avez dû rencontrer quelques difficultés, parce que le code devient vraiment compliqué. Il y a beaucoup de lignes, des chiffres de partout, et toutes les lignes se ressemblent.
On va reprendre le code de l'activité de la maison sans les menuiseries, et je vais faire un tour de magie qui va simplifier le code.
Donc pour rappel, voilà le code initial :
from turtle import *
#Un carré pour les murs
penup()
goto(0, 0)
pendown()
pencolor("red")
fillcolor("red")
begin_fill()
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
left(90)
forward(100)
end_fill()
# Un triangle pour le toit
penup()
goto(-125, 100)
pendown()
pencolor("brown")
fillcolor("brown")
begin_fill()
forward(150)
left(120)
forward(150)
left(120)
forward(150)
end_fill()
done()
Je me concentre pour accumuler du mana autour de moi...
HIPPITY HOPPITY, Le code Python est mieux écrit !
from turtle import *
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille_x)
left(90)
forward(taille_y)
left(90)
forward(taille_x)
left(90)
forward(taille_y)
end_fill()
def dessiner_triangle_equi(base_x, base_y, taille, couleur):
penup()
goto(base_x - taille/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
end_fill()
#un rectangle pour les murs
dessiner_rectangle(0, 0, 100, 100, "red")
#un triangle pour le toit
dessiner_triangle_equi(0, 100, 150, "brown")
done()
Activité : menuiseries V2
Copiez-collez le code ci-dessus et vérifiez qu'il affiche bien la maison sans les menuiseries.
Modifiez le code pour ajouter les menuiseries.
from turtle import *
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille_x)
left(90)
forward(taille_y)
left(90)
forward(taille_x)
left(90)
forward(taille_y)
end_fill()
def dessiner_triangle_equi(base_x, base_y, taille, couleur):
penup()
goto(base_x - taille/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
end_fill()
dessiner_rectangle(0, 0, 100, 100, "red")
#un rectangle pour la porte
dessiner_rectangle(20, 0, 30, 60, "brown")
dessiner_triangle_equi(0, 100, 150, "brown")
#un triangle pour la fenetre
dessiner_triangle_equi(0, 125, 60, "white")
done()
Est-ce plus simple de faire les menuiseries maintenant qu'avant ? Essayez d'expliquer pourquoi.
NE REGARDEZ PAS LA SOLUTION, APPELEZ VOTRE PROF. LA SOLUTION EST UNIQUEMENT LA POUR L'APPRENTISSAGE EN AUTONOMIE.
A priori, c'était plus simple, parce qu'au lieu de devoir écrire des tas de lignes compliquées et floues, vous avez simplement ajouté deux lignes relativement claires.
On va voir dans la suite du chapitre qu'il y a un peu plus que ça en réalité.
Activité : analyse
Cette activité peut être faite en petit groupe.
Expliquez précisément avec vos mots ce que fait la ligne
N'hésitez pas à expérimenter un peu en changeant les valeurs pour voir ce qu'elles changent sur le dessin.
NE REGARDEZ PAS LA SOLUTION, APPELEZ VOTRE PROF. LA SOLUTION EST UNIQUEMENT LA POUR L'APPRENTISSAGE EN AUTONOMIE.
La ligne dessine un rectangle, dont la base est en (0, 0), qui fait 100 de large et 100 de haut, de couleur rouge ("red")
Expliquez avec vos mots ce que fait la ligne
N'hésitez pas à expérimenter un peu en changeant les valeurs pour voir ce qu'elles changent sur le dessin.NE REGARDEZ PAS LA SOLUTION, APPELEZ VOTRE PROF. LA SOLUTION EST UNIQUEMENT LA POUR L'APPRENTISSAGE EN AUTONOMIE.
La ligne dessine un triangle equilatéral, dont la base est en (0, 100), de coté 150, de couleur marron ("brown")
Expliquez ce que fait le morceau de code suivant :
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille_x)
left(90)
forward(taille_y)
left(90)
forward(taille_x)
left(90)
forward(taille_y)
end_fill()
En particulier, à quoi servent les noms listés entre parenthèse dans cette ligne :
NE REGARDEZ PAS LA SOLUTION, APPELEZ VOTRE PROF. LA SOLUTION EST UNIQUEMENT LA POUR L'APPRENTISSAGE EN AUTONOMIE.
Ce morceau de code décrit comment dessiner un rectangle.
Les noms listés dans cette ligne sont les caractéristiques du triangle : la position de sa base, sa taille, et sa couleur.
Fonctions
Vous venez juste de voir un des outils les plus importants que fournissent les langages de programmation : les fonctions.
Attention
Cette section formalise ce que vous avez probablement déjà compris dans la section précédente.
En cas de doute, n'hésitez pas à poser des questions à votre prof.
Une fonction permet de définir et nommer une nouvelle opération, potentiellement complexe:
def print_sapin(): #nom_de_l_operation
#instructions_de_l_operation
print(" * ")
print(" * ")
print(" *** ")
print(" *** ")
print(" *** ")
print(" ***** ")
print(" ******* ")
print("*********")
print(" ### ")
print(" ### ")
puis de l'exécuter ailleurs dans le code simplement en l'appelant par son nom :
Remarque
Vous avez déjà appelé pleins de fonctions : print, input, begin_fill, ...
En utilisant les fonctions, on peut découper le code en opération séparées de manière à le garder toujours relativement simple à lire et à écrire.
Vous l'avez déjà expérimenté dans la section précédente : après le tour de magie qui a défini comment dessiner un rectangle et un triangle, c'etait beaucoup plus facile de rajouter les menuiseries à la maison.
Reprenons le code de la maison avec les menuiseries. Il est divisé en 3 blocs :
La séquence principale (le code qui n'est dans aucune fonction) :
Le code pour dessiner un rectangle :
Remarquez que ces 3 blocs sont indépendants les uns des autres : on peut comprendre chacun des blocs sans avoir à aller lire en détail les autres blocs. Ca veut dire que si l'on découpe correctement notre code, on peut faire des programmes de plusieurs millions de lignes sans jamais avoir à traiter plus de quelques dizaines de lignes à la fois au maximum.
Parametres
Souvent, une fonction peut-être paramètrée, c'est à dire qu'on peut lui passer des valeurs avec lesquelles travailler au moment de l'appel :
#on dessine un rectangle,
# en position x = 0
# | en position y = 0
# | | de largeur 100
# | | | de hauteur 100
# | | | | de couleur rouge
dessiner_rectangle(0, 0, 100, 100, "red")
Voici un autre exemple :
Les paramètres d'une fonction sont nommés dans la ligne def de la définition de la fonction. Ils peuvent ensuite être utilisés dans la fonction comme des variables.
# le dessin du rectangle a les parametres suivants :
# base_x -> sa position x
# base_y -> sa position y
# taille_x -> sa largeur
# taille_y -> sa hauteur
# couleur
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y) #ici, on utilise base_x, taille_x, base_y
pendown()
setheading(0)
pencolor(couleur) #ici, on utilise couleur
fillcolor(couleur) #ici, on utilise couleur
begin_fill()
forward(taille_x) #ici, on utilise taille_x
left(90)
forward(taille_y) #ici, on utilise taille_y
left(90)
forward(taille_x) #ici, on utilise taille_x
left(90)
forward(taille_y) #ici, on utilise taille_y
end_fill()
TODO ajouter exercice
Valeur de retour
Une fonction peut aussi retourner une valeur que l'on peut utiliser après l'avoir appelée. C'est le cas de la fonction input que vous avez déjà utilisé :
#input retourne la saisie de l'utilisateur
#que l'on stocke ici dans la variable réponse
reponse = input("Entrez votre nom:")
Quand on définit une fonction, on utilise return pour lui faire retourner une valeur :
Activité
Copiez-collez la fonction ci-dessus dans un fichier à part, puis utilisez-là pour écrire un programme qui :
- demande deux nombres à l'utilisateur
- appelle la fonction pour les additionner
- affiche le résultat
Quand l'instruction return s'execute, l'execution de la fonction est interrompue.
Activité
Copiez-collez le code suivant dans un fichier à part, et executez-le. Que remarquez vous ? Expliquez.
Exercices
Ecrire une fonction compter qui prends un nombre n en paramètres, et affiche les n + 1 premiers entiers (zéro inclus).
puis l'utiliser pour écrire un programme qui demande un nombre m à l'utilisateur, et appelle compter(m).
- Commencez par déclarer et écrire la fonction
- N'oubliez pas d'indenter son corps
- A L'intérieur de la fonction, vous devez utiliser une boucle
while.
Voici un programme à compléter :
Plusieurs maisons
Activité : fonction maison
Reprenez le code de l'activité précédente. Déplacez ces lignes :
dessiner_rectangle(0, 0, 100, 100, "red")
dessiner_rectangle(20, 0, 30, 60, "brown")
dessiner_triangle_equi(0, 100, 150, "brown")
dessiner_triangle_equi(0, 125, 60, "white")
dans une fonction dessiner_maison, puis appelez-là pour dessiner la maison.
from turtle import *
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille_x)
left(90)
forward(taille_y)
left(90)
forward(taille_x)
left(90)
forward(taille_y)
end_fill()
def dessiner_triangle_equi(base_x, base_y, taille, couleur):
penup()
goto(base_x - taille/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
end_fill()
#on crée une fonction dessiner_maison qui dessine la maison
def dessiner_maison():
dessiner_rectangle(0, 0, 100, 100, "red")
dessiner_rectangle(20, 0, 30, 60, "brown")
dessiner_triangle_equi(0, 100, 150, "brown")
dessiner_triangle_equi(0, 125, 60, "white")
#puis on l'appelle
dessiner_maison()
done()
Activité : plusieurs maisons
Modifiez la fonction dessiner_maison pour lui ajouter deux paramètres x et y, qui permettent de choisir où dessiner la maison.
Appelez-là ensuite plusieurs fois pour dessiner plusieurs maisons à diverses positions.
TODO ajouter visuel ?
Remarque : vous pouvez changer la vitesse de la tortue en utilisant speed( VITESSE ), par exemple speed(5).
Il faut modifier les coordonnées des formes que vous dessinez en ajoutant les coordonnées de la maison :
devient
from turtle import *
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur):
penup()
goto(base_x - taille_x/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille_x)
left(90)
forward(taille_y)
left(90)
forward(taille_x)
left(90)
forward(taille_y)
end_fill()
def dessiner_triangle_equi(base_x, base_y, taille, couleur):
penup()
goto(base_x - taille/2, base_y)
pendown()
setheading(0)
pencolor(couleur)
fillcolor(couleur)
begin_fill()
forward(taille)
left(120)
forward(taille)
left(120)
forward(taille)
end_fill()
#on ajoute les parametres x y
def dessiner_maison(x, y):
dessiner_rectangle(x, y, 100, 100, "red") #on les utilise
dessiner_rectangle(20 + x, y, 30, 60, "brown")
dessiner_triangle_equi(x, 100 + y, 150, "brown")
dessiner_triangle_equi(x, 125 + y, 60, "white")
speed(100)
#on dessine plusieurs maisons
dessiner_maison(0, 0)
dessiner_maison(200, 0)
dessiner_maison(-100, -200)
dessiner_maison(100, -120)
dessiner_maison(300, -160)
done()
Erreurs et trace d'appel
Les fonctions peuvent parfois rendre les erreurs plus compliquées à comprendre et à corriger.
Observez ce programme Python :
def addition(a, b):
return a + b
print("10 et 20 font", addition(10, 20))
print("20 et 30 font", addition(20, "30"))
Si on le lance, on a l'erreur suivante :
Traceback (most recent call last):
File "<basthon-input-1-945c13bc68f9>", line 5, in <module>
print("20 et 30 font", addition(20, "30"))
^^^^^^^^^^^^^^^^^^
File "<basthon-input-1-945c13bc68f9>", line 2, in addition
return a + b
~~^~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Analysons un peu cet erreur en partant du bas.
La première ligne
nous dit que l'on a essayé de faire un + entre un entier et une chaîne de caractères. Python ne sait pas faire ça donc il lève une erreur.
Les lignes suivantes :
Nous disent quel morceau de code à déclenché l'erreur : ligne 2, dans la fonction addition.
Or, ici, on a un problème : la fonction addition est appelée deux fois dans le code :
Comment savoir quel appel a déclenché l'erreur ? C'est simple, il suffit de regarder les lignes suivantes dans l'erreur :
File "<basthon-input-1-945c13bc68f9>", line 5, in <module>
print("20 et 30 font", addition(20, "30"))
^^^^^^^^^^^^^^^^^^
Maintenant, on sait que c'est l'appel addition(20, "30"), ligne 5, qui a conduit à l'erreur, et on peut corriger.
Docstring
On peut documenter ce que fait une fonction à l'aide d'une docstring, une chaine de caractère spéciale entre trois paires de ' ou " placée juste en dessous de la ligne def, comme suit :
def dessiner_rectangle(base_x, base_y, taille_x, taille_y, couleur)
"""dessine un rectangle
base_x, base_y : coordonnées du centre du côté bas du rectangle
taille_x : largeur du rectangle
taille_y : hauteur du rectangle
couleur : la couleur de remplissage du rectangle
"""
# [...] le code ici
On reviendra plus tard sur les docstrings. Je vous conseille d'en ajouter dans votre code pour expliquer vos fonction quand c'est nécessaire.
TP (a rendre) : un dessin complet
TP : dessin
Utilisez Turtle et les fonctions pour créer un dessin "complet", de ce style :

Bien entendu, vous n'êtes pas limités à un dessin de montagne. Vous pouvez choisir tout autre chose.
CE TP EST A RENDRE, ET POURRA ETRE NOTE. Il vous est demandé de remplir les critères suivants :
- Avoir au moins 3 objets différents qui apparaissent au moins 2 fois dans le dessin (par exemple, une maison, un sapin et une montagne)
- Votre dessin doit être significativement différent des autres dessins des membres de la classe : changer une ou deux valeur n'est pas suffisant !
- Le code doit être structuré avec des fonctions comme vu dans le chapitre.
- Vous devez être capables d'expliquer et modifier votre code si on vous le demande. Vous pouvez donc reprendre le code de camarades, a condition de le comprendre.
- Ne pas remplir les critères est acceptable si vous avez demandé régulièrement de l'aide et fait des efforts.
Accrochez-vous et ne vous laissez pas abattre. N'hésitez pas à expérimenter ou demander de l'aide.
Si vous êtes arrivés au bout du TP et que vous remplissez les critères, vous pouvez améliorer encore votre dessin, ou éventuellement vous frotter à une des extensions, ou même aux deux.
TP : extension 1, aléatoire
Ajouter la ligne:
en haut d'un fichier Python vous donne accès à la fonction randint :
# randint retourne un nombre entier
# aléatoire compris entre mini (inclus) et maxi (inclus)
nombre = randint(mini, maxi)
# example :
nombre = randint(10, 20)
print(nombre) #affiche un nombre choisi aléatoirement entre 10 et 20
Utilisez cette fonction pour ajouter des variations aléatoires dans vos objets.
Voici par exemple un lot de sapins randomisés, c'est à dire avec des variations aléatoires :

TP : extension 2 (difficile), perspective
Vous pouvez donner une illusion que votre dessin est en 3 dimensions, c'est la perspective.
La perspective fonctionne avec deux critères :
- Les objets plus loins apparaissent plus petit, et plus ils sont proches
- Un sol plat, plus on s'éloigne, et plus les objets loin apparaissent légèrement plus "haut" dans l'image.
Voici par exemple une forêt de sapins en perspective :

Exercices
Exercice
Observez le code bout de code suivant :
A quoi sert le mot clé def ?
Il sert à définir une fonction.
Quel est le nom de la fonction définie dans ce code ?
Le nom de la fonction est chats
Combien d'arguments cette fonction a-t-elle ? Quels sont leurs noms ?
Cette fonction a un seul argument, n. La liste des arguments d'une fonction est définie entre les parenthèses.
A quoi servent les arguments d'une fonction ?
Les arguments d'une fonction servent à donner des valeurs au corps de la fonction.
Exercice
Observez le code de la fonction suivante :
Combien d'arguments cette fonction admet-elle ? Quels sont leurs noms ?
cette fonction admet 2 arguments : a et b.
A quoi sert le mot clé return
Le mot clé return sert à dire quelle valeur la fonction retourne
Que se passe t'il quand on appelle une fonction qui retourne une valeur dans une expression ?
Par exemple
Exploration
Ecrivez une fonction compter qui prends un entier n >= 0 en paramètre, et affiche les nombres entiers de n à 0 par ordre décroissant.
La fonction doit absolument faire moins de 10 lignes, et vous n'avez pas le droit de déclarer d'autre fonction.
Dans le corps de la fonction, la seule structure de contrôle autorisée est un if, sans else, ni elif.
affiche
Vous savez qu'on peut appeler une fonction depuis le corps d'une autre fonction.
Mais saviez-vous qu'une fonction peut s'appeler elle-même ?
Executez le code suivant :
Observez bien sa sortie.
Essayez d'executer le code suivant. Observez bien sa sortie. Comment le modifier pour qu'il s'arrête à 0 ?
Reprenons le code de la fonction de l'exercice précédent.
def compter(n):
print(n)
# On utilise la valeur de n comme un critère d'arrêt.
if n > 0:
compter(n-1)
Essayez d'appeler compter(n), avec une très grande valeur de n. Par exemple, 1000000. Laissez tourner un peu le programme jusqu'a qu'il s'arrête.
Que se passe-t-il ?
A votre avis, pourquoi ?
Relisez bien la partie du cours sur les traces d'appel.
A votre avis, où est stockée la pile d'appel ?
Après un certain temps, le programme lève une erreur.
Une erreur de récursion est survient quand la pile d'appel grandit trop.
La pile d'appel est stockée dans la mémoire de l'ordinateur. Comme la mémoire n'est pas infinie, les systèmes d'exploitation et les interprêteurs limitent la taille de la pile d'appel, et donc le nombre d'appel imbriqués qui peuvent être fait.
Si on fait trop d'appel, le programme est alors terminé en erreur. C'est ce qu'on appelle un dépassement de pile.
Voici un code incomplet
## vous pouvez définir d'autres fonctions.
def ap(o, a, b):
return o(a,b)
def afficher_addition(a, b):
m = ## remplacez ce commentaire par qqch
print(ap(m, a, b))
afficher_addition(10, 20)
Sans modifier la fonction ap, et en ne modifiant la fonction afficher_addition qu'à l'endroit indiqué en commentaire, faites en sorte que ce programme affiche EXACTEMENT
Vous pouvez définir des fonctions supplémentaires si besoin.
Il y a deux méthodes.
L'une demande de bien analyser ce que fait la fonction ap.
L'autre est "très simple" mais conduit à un code très peu clair.
Executez le code suivant :
Peut-être celà vous aidera-t-il...
En Python, on peut passer une fonction comme argument d'une autre fonction.
La fonction ap prends une fonction o et deux arguments supplémentaires a et b en entrée,
et retourne le résultat de l'appel o(a,b)
On va alors créer une fonction addition et la passer en argument o à ap dans afficher_addition.
def addition(a, b):
return a + b
def ap(o, a, b):
return o(a,b)
def afficher_addition(a, b):
m = addition
print(ap(m, a, b))
afficher_addition(10, 20)
En Python comme dans beaucoup d'autres langages, les fonction sont des valeurs, et peuvent être donc stockées dans des variables et passées en arguments à d'autres fonctions. Nous verrons bien plus loin dans ce cours que cette propriété permet de faire du code extrêmement concis et flexible, et fait partie d'un concept plus large qu'on appelle la généricité.
En Python, on peut redéfinir une fonction. C'est à dire définir une fonction avec le même nom qu'une fonction déjà existante. C'est alors la définition vue en dernier qui sera utilisée. On aurait donc pu redéfinir afficher_addition juste avant son appel :
## vous pouvez définir d'autres fonctions.
def ap(o, a, b):
return o(a,b)
def afficher_addition(a, b):
m = 0 ##ici, on met une valeur juste pour que l'interpréteur ne râle pas
print(ap(m, a, b))
def afficher_addition(a, b):
print(a + b)
afficher_addition(10, 20)
Redéfinir des fonctions est une en Python une mauvaise pratique, parce qu'avoir deux définitions pour une même fonction peut induire en erreur.
Implémentez une fonction addition_partielle(n), de manière à ce que l'appel suivant :
Vous pouvez définir une fonction dans une fonction !
On va créer la fonction addition_partielle(n) de manière à ce qu'elle retourne une fonction ajout(m) qui retourne n + m.
Cette capacité à créer des fonction dynamiquement, c'est à dire pendant l'execution du programme, combinée au fait que l'on peut utiliser une fonction en tant que valeur, permet dans certains cas de faire des programmes très facilement extensibles et quand même très concis !
Les essentiels
Au programme
Une fonction se déclare et se définit avec le mot clé def et la syntaxe suivante :
arg1 et arg2 sont les arguments ou paramètres de la fonction. Une fonction peut avoir zéro, un ou plusieurs arguments, séparés par des virgules.
On appelle une fonction avec la syntaxe suivante :
où val1 et val2 sont des valeurs.
l'instruction return permet à la fonction de retourner une valeur, qu'on peut alors utiliser dans une expression.
Une fonction peut appeler une autre fonction :
Si on veut appeler une fonction, il faut qu'elle ait été définie plus haut dans le code.
Quand on appelle une fonction, c'est l'ordre des arguments qui importe, pas leurs noms.
-
Mesuré avec scc (https://github.com/boyter/scc) le 13/09/2022 à partir des dépôts GitHub ou GitLab, sur la branche principale. ↩
-
C'est un langage pour automatiser la compilation. les fichiers de configuration pour pouvoir compiler LLVM font 73000 lignes au total. ↩
-
http://lotrproject.com/statistics/books/wordscount ↩