4 Fonctions - Cours

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 8

Algorithmique et programmation 1

L1 Mathématiques - L1 Informatique
Semestre 1

Chapitre 4 - Fonctions

En programmation, une fonction est un morceau de programme, portant en général un nom, acceptant zéro, un ou
plusieurs paramètres et produisant le plus souvent un résultat. Des exceptions existent, mais la forme la plus courante
d'une fonction est donc proche de celle d'une fonction mathématique.

L'utilisation de fonctions améliore les aspects suivants du code :

Lisibilité : séparer une partie du programme (par exemple un gros calcul compliqué)
Modularité : réutiliser le même code plusieurs fois (évite de recopier le code)
Généricité : changer la valeur des paramètres (même calcul mais avec différentes valeurs de départ)

Fonctions prédéfinies et bibliothèque standard


En Python, il existe un grand nombre de fonctions prédéfinies, que nous avons déjà utilisées, par exemple :

int(obj) : 1 paramètre, 1 résultat. Reçoit en paramètre un objet (par exemple str ou float ), essaie de le
transformer en entier et renvoie l'entier obtenu.

In [ ]: int("34")

len(obj) : 1 paramètre, 1 résultat. Reçoit un objet (par exemple str ) et renvoie sa longueur.

In [ ]: len("34")

randint(mini, maxi) : 2 paramètres, 1 résultat. Reçoit deux nombres, et renvoie un entier aléatoire compris
entre ces deux nombres (inclus).

In [ ]: from random import randint


randint(1, 34)

Il y en a beaucoup d'autres, comme print, input, float, str... .

Ces fonctions sont appelées prédéfinies (ou built-in). Il n'est bien sûr pas question de les connaître toutes par coeur. La
totalité des fonctions prédéfinies de Python est documentée (https://docs.python.org/3/), en particulier sur cette page
(https://docs.python.org/3/library/functions.html).

Il existe également de nombreux modules officiels (par exemple le module random ), c'est-à-dire des bibliothèques de
fonctions, de types et d'objets, dont on trouvera la description ici (https://docs.python.org/3/library).
Définition de fonction
Pour définir une nouvelle fonction on utilise la syntaxe suivante :

# ligne suivante : en-tête de fonction


def nom_fonction(param_1, ..., param_n):
# corps de la fonction
# utilisant param_1 à param_n
...
# peut renvoyer un résultat :
return resultat

Une fonction peut :

prendre un certain nombre de paramètres (ici, 𝑛, qui s'appellent param_1 à param_n )


renvoyer une valeur (via l’instruction return )

Appel de fonction
Une fois définie, nom_fonction peut être utilisée dans le code (on parle d'un appel) en indiquant entre parenthèses
ses paramètres séparés par des virgules :

# définition de fonction
def nom_fonction(param_1, ..., param_n):
...

# reste du programme
...
# appel de la fonction :
une_var = nom_fonction(expr_1, ..., expr_n)

Il n'est pas possible d'appeller une fonction qui n'est pas définie au moment de l'appel !

Exemple : fonction à paramètres et résultat

In [ ]: # fonction à deux paramètres produisant un résultat


def maximum(a, b):
if a > b:
return a
else:
return b

nb1 = int(input())
nb2 = int(input())

# On appelle la fonction et on garde le résultat dans c :


c = maximum(nb1, nb2)
print("le max de", nb1, "et", nb2, "est", c)

# On peut aussi utiliser directement le résultat :


print("le max de", nb1, "et", nb2, "est", maximum(nb1, nb2))
Entraînement : Décrire l'exécution pas à pas du programme (avec état de la mémoire). On peut aussi essayer avec
Python Tutor (http://www.pythontutor.com/visualize.html#code=%23%20fonction%20%C3%A0%20deux%20param
%C3%A8tres,%20sans%20effet%20de%20bord%0Adef%20maximum%28a,%20b%29%3A%0A%20%20%20
%20if%20a%20%3E%20b%3A%0A%20%20%20%20%20%20%20%20return%20a%0A%20%20%20%20else
%3A%0A%20%20%20%20%20%20%20%20return%20b%0A%20%20%20%20%0Anb1%20%3D%20int%28input
%28%29%29%0Anb2%20%3D%20int%28input%28%29%29%0A%0A%23
%20On%20appelle%20la%20fonction%20et%20on%20garde%20le%20r%C3%A9sultat%20dans%20c%20%3A
%0Ac%20%3D%20maximum%28nb1,%20nb2%29%0Aprint%28%22le%20max%20de%22,%20nb1,
%20%22et%22,%20nb2,%20%22est%22,%20c%29%0A%0A%23
%20On%20peut%20aussi%20utiliser%20directement%20le%20r%C3%A9sultat%20%3A%0Aprint
%28%22le%20max%20de%22,%20nb1,%20%22et%22,%20nb2,%20%22est%22,%20maximum%28nb1,%20nb2
%29%29&cumulative=false&curInstr=0&heapPrimitives=true&mode=display&origin=opt-frontend.js&py=3&
rawInputLstJSON=%5B%5D&textReferences=false).

Exemple : fonction sans paramètre


En général, une fonction sans paramètre a toujours le même comportement. Dans l'exemple suivant, on utilise un
générateur pseudo-aléatoire, ce qui explique que la fonction ne renvoie pas toujours le même résultat. Une fonction
pourrait aussi recevoir des données depuis l'extérieur (utilisateur, requête réseau...).

In [ ]: from random import randint

def lance_de() :
return randint(1,6)

compteur = 1
while lance_de() != 6:
compteur = compteur + 1
print('Obtenu un 6 en', compteur, 'jets de dé.')

Exemple : fonction sans valeur de retour


Si l'exécution arrive à la dernière instruction du corps de la fonction sans rencontrer d'instruction return expr , alors
la valeur de retour par défaut est None (même comportement si return seul).

In [ ]: from turtle import *

def trace_polygone(nb_cotes, taille_cote):


down()
i = 0
while i < nb_cotes:
forward(taille_cote)
left(360 / nb_cotes)
i = i + 1

# faire une affectation ici ne servirait à rien (essayer !)


trace_polygone(5, 100)
exitonclick()

Erreur fréquente : confusion (paramètre / saisie) et (retour / affichage)


Les programmeurs débutants confondent très souvent la notion de paramètre et celle de saisie (au clavier par exemple)
et la notion de valeur de retour avec celle de valeur affichée.
In [ ]: # ATTENTION CECI EST INCORRECT, A NE PAS REPRODUIRE !!!
def pgcd(a, b):
a = int(input()) # NON !
b = int(input()) # NON !
while a % b != 0:
r = a % b
a = b
b = r
print("le pgcd est", b) # NON !

**NE SURTOUT PAS PROGRAMMER COMME ÇA !**

Comment écrire un programme vérifiant si trois entiers sont premiers entre eux à l'aide de cette fonction ?
Combien ce programme ferait-il de saisies ?
Qu'afficherait ce programme ?

In [ ]: # essayons de calculer le pgcd de trois nombres


pgcd() # saisit deux nombres et calcule leur pgcd
... # je ne sais pas comment continuer !

Composition de fonctions

In [ ]: def pgcd(a, b):


while a % b != 0:
r = a % b
a = b
b = r
return b

def premiers_entre_eux(a, b):


return pgcd(a, b) == 1

# programme principal :
m = int(input())
n = int(input())
o = int(input())
if (premiers_entre_eux(m, n)
and premiers_entre_eux(n, o)
and premiers_entre_eux(o, m)):
print("tous premiers entre eux")

Fonctions et espaces de noms

Reprenons un exemple précédent en changeant le nom des variables :

In [ ]: def maximum(a, b):


if a > b:
b = a
return b

nb1 = int(input())
nb2 = int(input())
c = maximum(nb1, nb2)
print("le max de", nb1, "et", nb2, "est", c)

Entraînement : Tenter de prévoir l'effet de cette cellule, et le vérifier en l'exécutant.


In [ ]: def maximum(a, b):
if a > b:
b = a
return b

a = int(input())
b = int(input())
c = maximum(a, b)
print("le max de", a, "et", b, "est", c)

Entraînement : Tenter de prévoir l'effet de cette cellule, et le vérifier en l'exécutant.

Autre exemple important

Essayons d'écrire une fonction permettant d'intervertir les valeurs de deux variables :

In [ ]: def echange(a, b):


temp = a
a = b
b = temp

x = 1
y = 2
echange(x, y)
print(x, y)
print(temp)

Entraînement : Tenter de prévoir l'effet de cette cellule, et le vérifier en l'exécutant.


Sémantique d'un appel
Au moment d'un appel de fonction, un espace de noms local est créé. Il associe à chacun des paramètres la valeur de
l'expression correspondante dans l'appel. Les variables locales sont également créées dans ces espace de noms.

Notion d'espace de noms

Un espace de noms est un ensemble de noms (de variables, fonctions...) définies à un certain point d'un programme.
L'ensemble de tous les noms connus à un point du programme peut être constitué de plusieurs espaces de noms
superposés (du plus bas au plus haut) :

espace de nom global contenant les variables (fonctions, classes...) définies directement dans le programme
principal ;
empilement des espaces de noms locaux des appels de fonction en cours, dans l'ordre chronologique, contenant
chacun les paramètres de l'appel correspondant ainsi que les variables définies dans le corps de cette fonction
(variables locales).

L'empilement des espaces de noms locaux obéit à une politique de pile : le sommet correspond au dernier appel en
date. Quand cet appel se termine, son espace de nom est supprimé de la pile et l'exécution de l'appel précédent
reprend. Quand un nouvel appel est effectué, l'exécution de la fonction en cours s'interrompt, un nouvel espace de noms
local est créé et l'exécution de la fonction appelée commence.

En Python, il est possible d'accéder en lecture à n'importe quel nom défini dans un des espaces de noms empilés. Si
plusieurs espaces contiennent le même nom, c'est l'espace de nom le plus récent qui est sélectionné. Pour accéder en
écriture à une variable qui n'est pas dans l'espace de nom le plus récent, il faut utiliser les mots-clés global ou
non-local (à utiliser avec précaution).

Déroulement détaillé d'un appel

Considérons l'appel suivant :

def ma_fonction(p_1, ..., p_n):


...
return expr

# Appel de fonction (à l'intérieur d'une expression)


... ma_fonction(e_1, ..., e_n) ...

Voici la succession des étapes de l'appel :

Création d'un espace de noms local contenant p_1 à p_n au sommet de la pile d'appels
Chaque expression e_i est évaluée en une valeur v_i et affectée à la variable p_i
Exécution du corps de la fonction dans l'espace de noms local
Si la fonction exécute l'instruction return expr ou atteint la fin de son bloc d'instructions, l'espace de noms
local est détruit et l'expression appelante ma_fonction(e_1, ..., e_n) prend la valeur de expr
(respectivement None )
Reprise du programme principal dans l'espace global

Les noms p_1 à p_n sont parfois appelés paramètres formels, les valeurs v_1 à v_n paramètres effectifs. On
appelle parfois aussi paramètres (tout court) les paramètres formels et arguments les paramètres effectifs.

Entraînement : Pour chacun des trois exemples précédent, dessiner l'évolution de l'état de la mémoire pendant
l'exécution. Vérifier à l'aide de Python Tutor.
Documentation et test de fonctions

Chaînes de documentation (docstring)


Il est important d'indiquer par un commentaire à quoi sert une fonction que l'on a programmé. Cela permet de se
souvenir à quoi sert une fonction, quels sont ses paramètres et sa valeur de retour.

In [ ]: def triple(nombre):
'''
Fonction calculant le triple d'un nombre.
Paramètre : nombre (int ou float)
Résultat : le triple de nombre (même type)
'''
return nombre * 3

On peut accéder à la chaîne de documentation d'une fonction en tapant help(nom de la fonction) dans
l'interpréteur :

In [ ]: help(triple)

Cela fonctionne aussi pour les fonctions prédéfinies ou issues de modules :

In [ ]: from random import randint


help(randint)

Tests intégrés à la documentation (doctest)


Comme tout morceau de programme, chaque fonction doit être testée immédiatement pour s'assurer qu'elle fonctionne.

In [ ]: triple(3)

In [ ]: triple(9.0)

Plutôt que de perdre ces tests, il est utile de les intégrer à la documentation de la fonction, pour pouvoir s'y référer plus
tard. Si l'on change le code de la fonction, cela permet aussi de vérifier que son comportement reste correct.

In [ ]: def triple(nombre):
'''
Fonction calculant le triple d'un nombre.
Paramètre : nombre (int ou float)
Résultat : le triple de nombre (même type)

>>> triple(3)
9
>>> triple(9.0)
27.0
'''
return nombre + nombre + nombre + nombre

In [ ]: triple(3)

Il existe des outils qui permettent de lancer automatiquement tous les tests présents dans la documentation, et de
vérifier qu'ils produisent les résultats annoncés.
Par exemple, à la fin d'un programme, on peut écrire le code suivant pour lancer systématiquement tous les tests
présents dans le fichier :

import doctest
doctest.testmod()

Exemple :

In [ ]: def triple(nombre):
'''
Fonction calculant le triple d'un nombre.
Paramètre : nombre (int ou float)
Résultat : le triple de nombre (même type)

>>> triple(3)
9
>>> triple(9.0)
27.0
'''
return nombre * 3

def racine(nombre):
'''
Fonction calculant la racine carrée (positive) d'un nombre.
Paramètre : nombre (int ou float)
Résultat : la racine carrée de nombre (float)

>>> racine(0)
0.0
>>> racine(1)
1.0
>>> racine(4)
2.0
'''
return nombre ** (1/2)

import doctest
doctest.testmod()

In [ ]:

Vous aimerez peut-être aussi