Les fonctions

Les fonctions sont les éléments essentiels de tous les langages de programmation.

Conceptuellement il s'agit d'une sous-programme du programme principal : un bloc d'instructions dévolu à une tâche élémentaire.

Pensez par exemple aux fonctions aux fonctions mathématiques (sin, exp, ...). De nombreuses fonctions sont déjà prévues en Python par défaut. D'autres sont programmées et rangées dans des bibliohtèques spécialisées.

Le principe

Le fonctionnement d'une fonction est basée sur le principe suivant :

  • on l'appelle à l'aide de son nom...
  • ... en lui passant un ou plusieurs arguments
  • elle effectue ensuite des instructions et renvoie une valeur.

Lors d'un appel à une fonction, l'état du programme est « gelé ». Les variables qui étaient utilisée sont mises du côté et l'exécution est suspendue. Python va charger en mémoire la fonction demandée, en initialisant certaines variables (les paramètres) avec les valeurs données lors de l'appel.

À la fin du calcul, des valeurs sont renvoyées. En première approche, vous pouvez considérer que le nom de la fonction est remplacé directement par la valeur renvoyée.

Syntaxe

La syntaxe pour définir une fonction est, comme toujours avec Python, très légère :

def <nom de la fonction> (arg1, arg2, ...):
    """Description de la fonction"""

    <bloc d'instructions>

    return (<valeurs renvoyées>)
  • Le nom de la fonction est une chaîne de caractères sans espaces et ne commençant pas par un chiffre.

  • Les lignes suivantes sont entre """...""". Elles sont considérées comme un commentaire. Pour Python, il s'agit du descriptif de la fonction qui est affiché par exemple dans l'aide du programme.

  • La fonction return(...) renvoie la valeur entre parenthèse. On sort alors de la fonction (dont l'exécution s'arrête donc à ce moment là).

Un exemple : la fonction médiane

Écrivons donc une fonction qui va renvoyer la médiane de trois nombres

Précisons

  • le nom de la fonction : mediane ;
  • son ou ses arguments : ici il y en a trois, trois flottants notés a, b et c ;
  • ses instructions : on a vu le corps de la fonction dans l'introduction à la programmation.
  • la valeur renvoyée, selon le résutat du test.

Cela peut donner le code suivant :

In [5]:
def mediane(a, b, c):
    ''' Renvoie la médiane de trois nombres a, b et c '''
   
    if a > b:
        x = a
        y = b
    else:
        x = b
        y = a
    
    if x > c:
        if y > c:
            med = y
        else:
            med = c
    else:
        med = x
        
    return(med)
In [6]:
mediane
Out[6]:
<function __main__.mediane>
In [7]:
mediane()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-bd577d032c6a> in <module>()
----> 1 mediane()

TypeError: mediane() missing 3 required positional arguments: 'a', 'b', and 'c'
In [8]:
mediane(3,4,6)
Out[8]:
4
In [10]:
mediane(-1,-2,-3)
Out[10]:
-2

Précisons quelques points :

  • Dès qu'il est défini, le nom de la fonction devient un nom reservé. Il faut éviter de l'employer pour autre chose, en particulier pour une variable. C'est pourquoi dans le corps de la fonction la variable intermédiaire a été nommée med.
  • L'instruction return est essentielle. Si elle est omise, Python va silencieusement renvoyer une valeur par défaut : None. C'est une valeur purement conventionnelle.

On dit que cette valeur est renvoyée « silencieusement » car Python ne va pas prévenir qu'il manque une instruction return, tout en exécutant tout de même une telle instruction. Il va simplement croire que l'instruction return None est implicitement demandée.

  • Si on saisit les lignes précédentes dans un fichier et qu'on l'exécute, il ne se passe rien. La fonction n'est effectivement exécutée que si on l'exécute.

Un exercice

  1. Écrire une fonction max2 qui renvoie le plus grand de deux nombres a et b.
  2. Écrire une fonction moyenne qui calcule la moyenne de trois nombres a, b et c.
In [12]:
def max2(a,b):
    """Renvoie le maximum de a et b"""
    if a>=b:
        return a
    else:
        return b
In [13]:
def moyenne(a,b,c):
    return (a+b+c)/3
In [14]:
max2(10, 100)
Out[14]:
100

Portée des variables

Jouons un peu avec notre fonction return et observons quelques phénomènes... plutôt rassurants !

In [15]:
a = 1
vraimed = 5
med = 12
mediane (a, vraimed, med)
Out[15]:
5

Question Quelle est la valeur contenue dans la variable med après l'appel à la fonction mediane ?

In [16]:
med
Out[16]:
12

Ce qu'il faut remarquer, c'est que la variable med qui a été définie précédemment a été « remplacée » à l'intérieur de la fonction.

En effet les fonctions sont executées dans un état de mémoire transitoire.

  • Lorsque Python commence l'exécution de la fonction, tout ce qui a été défini précedemment est mis de côté, temporairement « oublié ».

  • Pendant l'exécution, les variables nécessaires sont définies.

  • Lorsqu'on sort de la fonction par un return, Python oublie (pour de bon !) tout ce qui a été définie dans la fonction. Il recharche en mémoire toute ce qui avait été défini avant.

C'est le phénomène de portée des variables. Les variables définies dans une fonction n'ont de sens que dans la fonction : elles sont dites locales. Les variables définies entre les fonctions (dans le corps du programme) sont dites globales. Elles sont accessibles à l'intérieur des fonctions, mais elles peuvent aussi être complétement redéfinies dans la fonction.

La programmation d'une fonction nécessite donc quelques précautions. L'une d'entre elles (et qui est une véritable règle d'or de la programmation) est que si vous avez besoin d'une valeur pour exécuter une fonction, alors cette valeur doit être passé comme paramètre de la fonction.

Exercices

Que renvoie le programme suivant ?

In [17]:
def f(x):
    return x + a

a = 5
f(3)
Out[17]:
8

Et celui-ci ?

In [18]:
def f(x):
    a = 12
    return x + a

a = 5
f(3)
Out[18]:
15

Et celui-là ?

In [19]:
def g(x):
    aa = 12
    return 1

def f(x):
    return x + aa

g(1)
f(3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-19-b9cc2bf4a29e> in <module>()
      7 
      8 g(1)
----> 9 f(3)

<ipython-input-19-b9cc2bf4a29e> in f(x)
      4 
      5 def f(x):
----> 6     return x + aa
      7 
      8 g(1)

NameError: name 'aa' is not defined

Que fait ce programme ?

In [20]:
def mediane(a, b, c):
    ''' Renvoie la médiane de trois nombres a, b et c '''
   
    if a > b:
        x = a
        y = b
    else:
        x = b
        y = a
    
    if x > c:
        if y > c:
            med = y
        else:
            med = c
    else:
        med = x
        
    return(med)

def moyenne(a, b, c):
    ''' Renvoie la moyenne de trois nombres '''
    return((a+b+c)/3)

def test(a, b, c):
    if moyenne(a,b,c)> mediane(a, b, c):
        return True
    else:
        return False