Comme en mathématiques, on définit la fonction puis on appelle la fonction (on l'utilise).
Etape 1 : définition
def f(x):
return x**2
Cette syntaxe se comprend intuitivement (mot clé "def" pour définition et mot clé "return" pour renvoyer la valeur calculée
au programme appelant la fonction).
Etape 2 : appels
f(4)
a = 1
f(a)
Vocabulaire
Dans la définition (def f(x):
), x est un symbole quelconque (variable muette des mathématiques)
appelé paramètre formel.
Lors d'un appel \(f(4)\) ou \(f(a)\), 4 et a sont des valeurs appelées arguments effectifs.
Avec ou sans instruction return
, une fonction renvoie toujours un résultat (qui peut être None).
Une fonction peut posséder un nombre quelconque de paramètres voire aucun.
Exercice 1 - Expliquer et corriger l'erreur suivante :
L'instruction return provoque une sortie immédiate de la fonction.
Une fonction peut ne rien retourner, c'est à dire retourner None
, attention à l'utilisation de la fonction dans ce cas.
Exemple : test avec plusieurs instructions return
.
Exercice 2 - Expliquer et corriger l'erreur suivante :
Exemple 1 : aucune instruction return, la fonction renvoie None
Exemple 2 : ci-dessous, dans le cas x < 0, la fonction renvoie None, ce qui peut provoquer une erreur à l'extérieur de la fonction.
Exercice 3 - Expliquer et corriger l'erreur suivante :
Pour récupérer les valeurs retournées, on utilise les techniques appelées "unpacking" ("dépaqueter", contraire d'empaqueter) :
Exercice 4 - Expliquer et corriger l'erreur suivante :
Une variable globale est disponible dans tout le programme y compris à l’intérieur des fonctions, c’est le cas de toutes les variables définies dans le corps du programme principal.
Une variable locale est une variable définie dans une fonction, elle n’existe qu’à l’intérieur de la fonction (elle n’est pas définie à l’extérieur de la fonction).
Cependant, il est possible d’utiliser une variable globale dans une fonction.
Ce problème de la portée des variables (scope en anglais) est très important et source de nombreuses erreurs.
L'utilisation de variables globales dans un programme est une très mauvaise méthode pour de très nombreuses raisons.
La variable a ci-dessous est globale car définie dans le corps du programme. L'instruction global
est facultative.
Remarque : la variable a est créée après la définition de la fonction mais avant l'appel de la fonction.
La variable a ci-dessous est locale car définie dans la fonction.
Exercice 5 - Expliquer et corriger l'erreur suivante :
Exercice 6 - Expliquer pour quelle raison aucune erreur n'apparaît :
Il est possible d'utiliser le même nom de variable pour une variable locale et une variable locale mais c'est maladroit car peu lisible.
Attention alors à l'utilisation de l'instruction global
!
Exemple 1 : pas d'instruction global
Exemple 2 : instruction global
présente
Attention : modifier une variable globale à l'intérieur d'une fonction est une pratique à proscrire absolument.
La façon correcte (lisible donc sûre) de modifier une variable globale est la suivante :
Rappel : un nom de variable est en réalité une adresse mémoire contenant une certaine valeur.
L'instruction a = 4
signifie qu'à l'adresse mémoire 0x2f35
(par exemple), est placée la valeur 4.
Attention, dans le cas d'un tableau L = [-2,5], l'adresse mémoire 0x1e89
(par exemple) associée à L contient en réalité l'adresse de la plage mémoire
où se trouvent les éléments du tableau et non le tableau lui-même. Autrement dit la valeur du tableau L est une adresse mémoire.
Conséquence : le comportement des fonctions vis à vis des nombres et des tableaux est différent.
Exemple 1 : argument numérique
Ci-dessous l'argument a n'est pas modifié par la fonction car c'est la valeur 1 qui est transmise (et non l'adresse mémoire associée à la variable a),
x est une variable locale qui reçoit la valeur de a.
Exemple 2 : argument de type tableau
Ci-dessous l'argument L est modifié par la fonction car c'est la valeur de L donc l'adresse mémoire associée au tableau qui est transmise.
C'est la raison pour laquelle l'instruction return
n'est pas indispensable.
Exemple 3 : argument de type sous-tableau
Attention, le comportement précédent disparaît si la valeur transmise est non pas le tableau mais une partie du tableau (un élément ou un slicing) car ce n'est plus l'adresse du tableau
qui est transmise mais la valeur des éléments (variables locales) :
Modification d'une partie d'un tableau :
Pour modifier une portion de liste à l'aide d'une fonction sans rencontrer ce problème deux stratégies sont envisageables :
- transmettre la liste entière ainsi que les index des éléments à modifier ;
- procéder à des copies (cf. ci-dessous).
Exercice 7 - Ecrire une fonction exo7(L,d,f) remplaçant tous les éléments d'index compris entre d et f par des zéros dans la liste L.
Exemple : avec L = [10,11,12,13,14,15], après execution de exo7(L,1,4), L contient [10, 0, 0, 0, 15].
Si on tente d'utiliser des sous-tableaux... c'est l'échec :
Mais si on effectue des copies, cela peut fonctionner (méthode à éviter : les copies augmentent considérablement le temps d'exécution).