Programmation Python — Séance 4 : Fonctions, modules et robustesse

Une fonction est un bloc de code nommé et réutilisable.
Télécharger le notebook Ouvrir dans Colab Les sorties sont celles enregistrées dans le notebook : rien n'est réexécuté.

DMI · FST · UCAD

On sait décider et répéter. Cette séance apprend à organiser le code en fonctions réutilisables, à réutiliser des modules tout prêts, à lire et écrire des fichiers, et à gérer les erreurs proprement avec try / except. Exécutez chaque cellule avec Maj + Entrée. Les cellules À vous sont à compléter.


1. Les fonctions

Une fonction est un bloc de code nommé et réutilisable. On la définit une fois avec def, puis on l’appelle autant de fois qu’on veut. return renvoie une valeur que l’on peut réutiliser. Comme pour if et for, le corps est un bloc indenté après les deux points.

def moyenne(a, b):
    return (a + b) / 2

print(moyenne(12, 16))
print(moyenne(9, 18))
14.0
13.5

À vous. Écrivez une fonction double(n) qui renvoie n * 2, puis affichez double(7).

# À vous : definissez double(n) qui renvoie n * 2, puis affichez double(7)

Une fonction peut prendre plusieurs paramètres. À l’appel, on fournit les arguments dans le même ordre.

def message(prenom, ville):
    return f"{prenom} habite a {ville}."

print(message("Fatou", "Dakar"))
Fatou habite a Dakar.

À vous. Écrivez une fonction presentation(nom, age) qui renvoie une phrase du type « Awa a 25 ans. », puis affichez le résultat pour un nom et un âge.

# À vous : definissez presentation(nom, age) qui renvoie une phrase, puis affichez-la

Un paramètre peut avoir une valeur par défaut : si l’argument n’est pas fourni à l’appel, la valeur par défaut est utilisée.

def saluer(nom, politesse="Bonjour"):
    return f"{politesse} {nom}"

print(saluer("Awa"))
print(saluer("Awa", "Bonsoir"))
Bonjour Awa
Bonsoir Awa

À vous. Écrivez une fonction prix_ttc(prix, taux=0.18) qui renvoie prix * (1 + taux), puis appelez-la une fois avec le taux par défaut et une fois avec taux=0.10.

# À vous : definissez prix_ttc(prix, taux=0.18), puis appelez-la avec et sans le taux

On documente une fonction avec une docstring : une courte phrase entre guillemets, juste sous le def. On la retrouve via .__doc__.

def carre(x):
    "Renvoie le carre de x."
    return x * x

print(carre(5))
print(carre.__doc__)
25
Renvoie le carre de x.

Une variable créée dans une fonction est locale : elle n’existe que le temps de l’exécution de la fonction, et n’est pas accessible à l’extérieur (c’est la portée).

def calcul():
    resultat = 5 * 3
    print("dans la fonction :", resultat)

calcul()
dans la fonction : 15

Portée. La variable resultat ci-dessus n’existe pas en dehors de calcul : y accéder après l’appel provoquerait une NameError. Pour récupérer une valeur calculée dans une fonction, il faut la renvoyer avec return.

Attention à la différence entre return et print : return renvoie une valeur réutilisable dans un calcul ; une fonction qui se contente d’afficher renvoie None.

def somme(a, b):
    return a + b

def affiche_somme(a, b):
    print(a + b)

x = somme(10, 5) + 100
print("x =", x)
y = affiche_somme(10, 5)
print("y =", y)
x = 115
15
y = None

À vous. Écrivez une fonction triple(n) qui renvoie n * 3 (avec return, pas print), puis utilisez-la dans un calcul : affichez triple(4) + 1.

# À vous : definissez triple(n) avec return, puis affichez triple(4) + 1

2. Les modules

Un module est une bibliothèque de code déjà écrit, qu’on importe pour la réutiliser. Python en fournit beaucoup en standard. import math donne accès aux outils mathématiques via math..

import math

print(math.sqrt(16))
print(math.pi)
4.0
3.141592653589793

À vous. Importez math et affichez la racine carrée de 81 avec math.sqrt.

# À vous : importez math et affichez math.sqrt(81)

On peut aussi importer seulement ce dont on a besoin, avec from module import nom. On l’utilise alors directement, sans le préfixe.

from math import sqrt

print(sqrt(25))
5.0

À vous. Importez uniquement la fonction sqrt depuis math, puis affichez sqrt(49).

# À vous : from math import sqrt, puis affichez sqrt(49)

3. Lire et écrire des fichiers

Un programme peut sauvegarder des données dans un fichier pour les retrouver plus tard. On ouvre un fichier avec open(), dans un bloc with qui le referme automatiquement à la fin. Le mode "w" écrit (et écrase), "r" lit (mode par défaut).

with open("villes.txt", "w") as f:
    f.write("Dakar\n")
    f.write("Louga\n")
    f.write("Mbour\n")

print("fichier ecrit")
fichier ecrit

\n marque une fin de ligne. On relit tout le contenu d’un coup avec .read().

with open("villes.txt") as f:
    contenu = f.read()

print(contenu)
Dakar
Louga
Mbour

À vous. Écrivez dans un fichier notes.txt trois notes (par exemple 12, 15, 18), une par ligne.

# À vous : ouvrez notes.txt en mode "w" et ecrivez trois notes, une par ligne (avec \n)

Le plus souvent, on parcourt un fichier ligne par ligne avec une boucle for. Chaque ligne se termine par \n, qu’on enlève avec .strip().

with open("villes.txt") as f:
    for ligne in f:
        print(ligne.strip())
Dakar
Louga
Mbour

À vous. Ouvrez villes.txt et affichez chaque ligne débarrassée de ses espaces de fin, avec une boucle for et .strip().

# À vous : parcourez villes.txt ligne par ligne et affichez chaque ligne avec .strip()

4. Gérer les erreurs : try / except

Certaines opérations peuvent échouer à l’exécution (convertir un texte non numérique, diviser par zéro, ouvrir un fichier absent). Plutôt que de laisser le programme planter, on essaie le code dans un bloc try, et on rattrape l’erreur dans un bloc except.

try:
    nombre = int("abc")
    print(nombre)
except ValueError:
    print("Ce n'est pas un nombre valide.")
Ce n'est pas un nombre valide.

À vous. Mettez int("12x") dans un try, et affichez un message dans un except ValueError.

# À vous : try: int("12x") ... except ValueError: affichez un message

On précise quelle erreur on rattrape (ici ZeroDivisionError). Cela évite de masquer des erreurs qu’on n’avait pas prévues.

try:
    resultat = 10 / 0
except ZeroDivisionError:
    print("Division par zero impossible.")
Division par zero impossible.

Une fonction peut intégrer un try / except pour rester robuste : elle renvoie une valeur de repli au lieu de planter.

def division_sure(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return "impossible"

print(division_sure(10, 2))
print(division_sure(10, 0))
5.0
impossible

À vous. Écrivez un try / except ZeroDivisionError qui tente d’afficher 20 / 0 et, en cas d’échec, affiche « division impossible ».

# À vous : try: print(20 / 0) ... except ZeroDivisionError: affichez un message

Récapitulatif

  • Fonction : def nom(parametres): + return ; s’appelle avec des arguments ; peut avoir des valeurs par défaut et une docstring.
  • Portée : une variable définie dans une fonction est locale ; pour en sortir une valeur, on la return.
  • return vs print : return renvoie une valeur réutilisable ; print affiche seulement (et la fonction renvoie None).
  • Modules : import math (puis math.sqrt), ou from math import sqrt.
  • Fichiers : with open("f.txt", "w") as f: pour écrire, "r" pour lire ; .read() ou une boucle for ligne par ligne ; with referme automatiquement.
  • Exceptions : try: le code risqué, except TypeErreur: le rattrapage ; préciser l’erreur attendue.

Prochaine séance — S5 : la programmation orientée objet (classes, objets, __init__, méthodes, héritage, polymorphisme).

Retour au sommet