Vous êtes sur une version archivée de lyceum.fr de l'année 2023/2024. Revenir au présent.

Chapitre 6: Fonctions

Contenus Capacités attendues Commentaires
Spécification

Prototyper une fonction.

Décrire les préconditions sur les arguments.

Décrire des postconditions sur les résultats.

Des assertions peuvent être utilisées pour garantir des préconditions ou des postconditions.

Si on écrit un programme qui nécessite souvent de réaliser les mêmes suites d’instructions, on peut alors définir une fonction qui évitera de réécrire constamment les mêmes instructions et de rendre le programme plus lisible.

En fonction des arguments donnés en entrée(X), la fonction renverra la valeur (Y) souhaitée.
En fonction des arguments donnés en entrée(X), la fonction renverra la valeur (Y) souhaitée.
©  CC BY-SA 3.0 via Wikimedia Commons

1 Définition d’une fonction

Une fonction possède un nom pour pouvoir être appelée et il est possible de lui communiquer des arguments.

En python la syntaxe de définition d’une fonction est la suivante:

Syntaxe (ATTENTION À L’INDENTATION)

def nom_de_ma_fonction(paramètres séparés par des virgules):
    instruction 1
    instruction 2
    ...
    return objet_renvoyé_par_ma_fonction

Pour appeler la fonction, il suffit de taper son nom avec les arguments entre parenthèse.

nom_de_ma_fonction(arg1, arg2,...)

En python, la convention PEP8 donne l’habitude de nommer les fonctions et variables avec des lettres minuscules et des tirets bas _ pour remplacer les espaces.

fonction energie_cinetique()

Nous prendrons comme exemple le calcul de l’énergie cinétique d’un véhicule afin d’illustrer quelques notions utiles sur l’utilisation des fonctions en python.

L’énergie cinétique d’un objet de masse m se déplaçant à la vitesse v est:

E c = 1 2 m v 2 Ec = \frac{1}{2} m v^{2}

Nous allons créer une fonction energie_cinetique qui calcule sa valeur à partir des paramètres masse et vitesse.

# On définit la fonction
def energie_cinetique(m, v):
    return 0.5*m*v**2

# On appelle la fonction pour un objet de 2kg ayant une vitesse de 3m/s
energie_cinetique(2, 3) 
9.0

Il est possible de définir des fonctions qui ne renvoient pas de valeur, on les nomme alors parfois procédure.

Ce type de fonction n’utilise pas l’instruction return. On peut s’en servir par exemple pour faire des affichages.

def affiche_ec(m, v):
    ec = 0.5*m*v**2
    print("L'énergie cinétique est:", ec, "J")

L’affichage s’effectue lors de l’appel de la procédure:

affiche_ec(1,10)

>>sortie

L'énergie cinétique est: 50.0 J

2 Prototyper une fonction

Pour expliquer le fonctionnement d’une fonction, on lui ajoute un prototype juste sous la ligne de définition. En Python les prototypes sont appelés docstrings. On peut y accéder dans le code source ou simplement en utilisant la fonction help().

Le prototype doit décrire le rôle de la fonction, le type des paramètres et le type de la valeur de retour.

def somme(a, b):
    """La somme de deux nombres.

    Renvoie la somme des deux nombres donnés en arguments

    Paramètres
    ----------
    a : int
        première valeur à ajouter
    b : int
        deuxième valeur à ajouter

    Renvoie
    -------
    int
        La somme des deux arguments de la fonction
    """
    return a + b

Maintenant, en tapant help(somme), vous aurez toutes les informations utilise pour utiliser la fonction.

help(somme)

>>sortie

Help on function somme in module __main__:

somme(a, b)
    La somme de deux nombres.
    
    Renvoie la somme des deux nombres donnés en arguments
    
    Paramètres
    ----------
    a : int
        première valeur à ajouter
    b : int
        deuxième valeur à ajouter
    
    Renvoie
    -------
    int
        La somme des deux arguments de la fonction

3 Réaliser des tests d’assertion

Pour être sûr que notre fonction donne les bons résultats, on utilise des tests d’assertion (affirmation en anglais) qui renvoient une AssertionError en cas d’erreur.

assertion

(Programmation) Expression évaluée à vrai. Wiktionnaire

On pourrait tester notre fonction somme sur des cas simples:

assert somme(1, 2) == 3
assert somme(0, 0) == 0
assert somme(10, -2) == 8
print("Tests passés avec succés:)")

>>sortie

Tests passés avec succés:)

En cas d’erreur (souvent en raison d’interventions humaines sur le code!), le programme est bloqué ce qui évite de le laisser tourner en faisant des erreurs qui pourraient être très dommageables dans certaines situations(banque, commerce, circulation…).

Par exemple, cette suite de tests avec des flottants ne réussi pas.

assert somme(0.0, 0.0) == 0.0
assert somme(10.0, -2.0) == 8.0
assert somme(0.1, 0.2) == 0.3
print("Tests passés avec succés:)")

>>sortie

AssertionError: 

Si vous ne voyez pas pourquoi, revoyez le chapitre sur l’encodage des nombres à virgule.

4 En plus

4.1 Le return est définitif!

Mise en garde

Une fonction ne peut exécuter qu’un return, tout return est définitif.

  1. Tout ce qui suit le return n’est pas exécuté, on parle de code mort(dead code en anglais).

    def exemple():
        return "Bonjour"
        print("Ce code ne sera pas exécuté(dead code)")
    
    # appel
    exemple()
    'Bonjour'
  2. Il peut y avoir plus return, mais un seul sera exécuté.

    def bonjour(genre):
        if genre == "M":
            return "Bonjour monsieur"
        elif genre == "F":
            return "Bonjour madame"
    
    # appel
    bonjour("F")
    'Bonjour madame'
  3. Il n’est pas nécessaire de placer un return dans un else car si on arrive après les conditions, sans retourner, ces conditions sont forcément non vérifiées.

    def bonjour(genre):
        if genre == "M":
            return "Bonjour monsieur"
        elif genre == "F":
            return "Bonjour madame"
        return "Bonjour"
    
    # comme G n'est pas dans les conditions c'est le return final qui est exécuté
    bonjour("G")
    'Bonjour'

4.2 Nommer les arguments de la fonction lors de l’appel

On peut préciser le nom des arguments dans l’appel de la fonction pour être plus explicite, on parle alors de keyword arguments:“arguments nommés”.

# On définit la fonction
def energie_cinetique(m, v):
    return 0.5*m*v**2
# On appelle la fonction pour un objet de 2kg ayant une vitesse de 3m/s
energie_cinetique(m=2, v=3)

Sortie:

L'énergie cinétique est: 50.0 J

L’avantage est qu’en plus d’être plus explicite, on peut alors appeler les arguments dans un ordre quelconque ce qui n’est pas le cas lorsque l’on ne nomme pas les arguments(ce type d’arguments est appelé positionnal argument: “argument positionnel”)

energie_cinetique(v=3, m=2)

Sortie:

L'énergie cinétique est: 50.0 J

4.3 Portée des variables

Les variables définies dans les fonctions, ses paramètres ou autres, sont appelés des variables locales, par opposition aux variables globales, qui sont définies dans flot d’exécution du programme.

# Je défini une variable globale x
x = 3
# Je défini une fonction avec comme paramètre x
def double(x):
  # Il s'agit d'une nouvelle variable locale x non liée à la variable globale x
  return 2 * x

# J'appelle la fonction double avec x = 2
double(2)
4

La variable globale x reste inchangée :

print(x)

>>sortie

3