PYTHON → ROBOTIQUE · 05

Séance 05 · Partie A · Python pas à pas

Fonctions.

Un grand programme est fait de petits morceaux qui font chacun une chose, bien. Une fonction, c’est un de ces morceaux, avec un nom.

Durée : 60 à 90 min · Objectifs : définir et appeler une fonction, paramètres et valeurs de retour, portée des variables, documenter et tester.

Ce que vous saurez faire à la fin
  • Transformer un bloc de code répété en fonction réutilisable.
  • Distinguer print (afficher) et return (renvoyer).
  • Comprendre pourquoi une variable créée dans une fonction n’existe pas dehors.
  • Découper un problème en fonctions avant de coder.

01 / Définir

def : donner un nom à un bloc

  • def + nom + () + : définit la fonction. Rien ne s’exécute encore.
  • saluer() appelle la fonction : le bloc s’exécute.
  • Définir une fois, appeler autant de fois qu’on veut.

Les parenthèses sont obligatoires à l’appel. saluer sans parenthèses désigne la fonction sans la lancer.

Vous en utilisez depuis le début

print(), input(), len(), int(), range() sont des fonctions écrites par les créateurs de Python. Aujourd’hui vous écrivez les vôtres. Le mécanisme est identique.

01 / Définir

Les paramètres : donner des informations à la fonction

  • distance et vitesse sont les paramètres : des variables qui reçoivent les valeurs à chaque appel.
  • 100 et 20 sont les arguments passés à cet appel.
  • On peut nommer les arguments pour plus de clarté.
Valeur par défaut

def avancer(distance, vitesse=20): rend vitesse optionnel : avancer(100) utilise 20. Les paramètres avec défaut se placent après ceux sans défaut. C’est ainsi que print(x, end=" ") fonctionne : end a la valeur par défaut "\n".

02 / Renvoyer

return : la fonction donne un résultat

  • return renvoie une valeur à l’endroit de l’appel et termine la fonction.
  • L’appel aire_disque(2) devient la valeur 12.57 : on peut la ranger, l’afficher, la calculer.
  • Une fonction sans return renvoie None.

02 / Renvoyer

print n’est pas return

L’erreur la plus fréquente de la séance

print montre une valeur à l’humain. return donne une valeur au programme. Une fonction de calcul doit renvoyer ; l’affichage se décide ailleurs. Décommentez la dernière ligne : double_affiche(3) renvoie None, et None * 2 est une TypeError. Règle pratique : si vous écrivez print dans une fonction de calcul, demandez-vous si ce n’est pas return que vous vouliez.

02 / Renvoyer

Renvoyer plusieurs valeurs, ou un booléen

Style

On écrit return n % 2 == 0 et non if n % 2 == 0: return True else: return False : la comparaison est déjà un booléen. Les fonctions qui renvoient un booléen se nomment souvent est_… ou a_… : le if se lit alors comme une phrase.

03 / Portée

Ce qui naît dans une fonction meurt avec elle

  • resultat est locale : elle existe seulement pendant l’exécution de calcul().
  • À l’extérieur, ce nom n’existe pas. C’est voulu : chaque fonction a son espace privé.
  • Pour récupérer la valeur : return, puis une variable extérieure.
Lecture de l’extérieur, écriture interdite

Une fonction peut lire une variable définie hors d’elle (dite globale), par exemple une constante GRAVITE = 9.81. Mais elle ne peut pas la modifier par simple affectation : elle créerait une locale du même nom. Le mot-clé global l’autorise, mais son usage est presque toujours signe d’un mauvais découpage. Préférez passer des paramètres et renvoyer des résultats : la fonction devient prévisible et testable.

03 / Portée

Même nom, variables différentes

Pourquoi c’est une bonne chose

Imaginez un programme de 5000 lignes écrit par cinq personnes. Si chaque fonction pouvait modifier n’importe quelle variable, personne ne pourrait raisonner sur rien. L’isolation des fonctions est ce qui permet de construire des logiciels de la taille d’un système d’exploitation ou d’un robot autonome. En séance 06, une nuance importante : une fonction qui reçoit une liste peut en modifier le contenu.

04 / Bien écrire

Documenter et tester une fonction

Pourquoi tester ?

La docstring (chaîne entre triples guillemets juste sous def) explique ce que fait la fonction ; help() l’affiche. Les assert vérifient des cas connus. Changez le 9 en 8 dans la formule : le premier test échoue immédiatement, avant que l’erreur ne se propage dans un programme de 1000 lignes. Les ingénieurs écrivent souvent les tests avant la fonction : ils savent alors précisément ce qu’ils doivent produire.

04 / Bien écrire

Découper un problème

Une fonction, une responsabilité

Chaque fonction fait une chose et son nom le dit. decider() ne lit pas de capteur et n’affiche rien : on peut la tester seule (assert decider(5) == "reculer"). Quand vous passerez au vrai robot, seules lire_capteur() et agir() changeront ; decider() restera identique. Cette séparation entre perception, décision et action est un principe de base en robotique. Le _ comme variable de boucle signale « je n’utilise pas cette valeur ».

05 / Défis

Défi ★ — Trois petites fonctions

Consigne

Écrire et tester : perimetre_rectangle(l, L), maximum3(a, b, c) (sans utiliser max) et est_majuscule(lettre) qui renvoie un booléen.

Correction
def perimetre_rectangle(l, L):
    return 2 * (l + L)

def maximum3(a, b, c):
    m = a
    if b > m:
        m = b
    if c > m:
        m = c
    return m

def est_majuscule(lettre):
    return "A" <= lettre <= "Z"

assert perimetre_rectangle(2, 3) == 10
assert maximum3(3, 9, 5) == 9 and maximum3(3, 3, 3) == 3
assert est_majuscule("R") and not est_majuscule("r")
print("OK")

Les lettres se comparent par ordre alphabétique (en réalité par code Unicode, séance 07). pass est une instruction qui ne fait rien : utile pour laisser un bloc vide provisoirement.

05 / Défis

Défi ★★ — Nombres premiers

Consigne

Écrire est_premier(n) qui renvoie True si n est premier (divisible seulement par 1 et lui-même, n ≥ 2). Puis afficher tous les nombres premiers inférieurs à 100 grâce à cette fonction.

Correction
def est_premier(n):
    if n < 2:
        return False
    for d in range(2, n):
        if n % d == 0:
            return False      # un diviseur trouvé : on sort tout de suite
    return True               # aucun diviseur : premier

for n in range(2, 100):
    if est_premier(n):
        print(n, end=" ")

Le return False dans la boucle joue le rôle d’un break : dès qu’on sait, on répond. Amélioration : il suffit de tester les diviseurs jusqu’à √n (si n = a × b, l’un des deux est ≤ √n). Écrivez range(2, int(n ** 0.5) + 1) et comparez le temps pour n = 10 000 019 avec time.perf_counter(). Ce sera l’objet de la séance 11.

05 / Défis

Défi ★★★ — Esprit prépa : la racine carrée de Héron

Consigne

Il y a 2000 ans, Héron d’Alexandrie calculait √a ainsi : partir de x = a, puis répéter x = (x + a / x) / 2. Chaque étape double environ le nombre de décimales exactes.

Écrire racine(a, precision=1e-10) qui répète tant que |x² − a| > precision et renvoie x. Comparer avec a ** 0.5. Compter le nombre d’itérations pour a = 2, 1000, 1 000 000.

Correction et ouverture
def racine(a, precision=1e-10):
    x = a
    iterations = 0
    while abs(x * x - a) > precision:
        x = (x + a / x) / 2
        iterations += 1
    return x, iterations

for a in (2, 1000, 1_000_000):
    r, n = racine(a)
    print(f"√{a} ≈ {r:.10f} en {n} itérations (Python : {a ** 0.5:.10f})")

Même pour un million, une quinzaine d’itérations suffisent : la convergence est quadratique. Cette méthode est un cas particulier de la méthode de Newton, que vous verrez en prépa, et c’est (à peu près) ce que fait le processeur de votre PC quand il calcule une racine. Question ouverte : pourquoi partir de x = a et pas de x = 1 ? Essayez les deux. Et que se passe-t-il pour a = 0 ?

06 / Vérification

Qu’affiche print(f(3)) si def f(x): return x + 5 ?

Deux questions supplémentaires

1. Que renvoie une fonction qui n’a pas de return ? None.

2. Peut-on avoir deux return dans une fonction ? Oui, par exemple dans les deux branches d’un if. Le premier atteint termine la fonction.

Référence

Les mots à retenir

MotDéfinition
FonctionBloc de code nommé, réutilisable, avec entrées et sortie.
ParamètreVariable de la fonction qui reçoit une valeur à l’appel.
ArgumentValeur effectivement passée lors d’un appel.
returnRenvoie un résultat et termine la fonction.
Variable localeCréée dans la fonction, invisible dehors.
DocstringTexte de documentation sous le def.
assertVérifie qu’une condition est vraie, sinon erreur.

Pour continuer

Vous savez construire des briques

Séance suivante : les listes et dictionnaires, pour donner à vos fonctions de vraies données à traiter.

À faire chez soi

Documentation

Tutoriel officiel : définir des fonctions

← Séance 04SommaireSéance 06 : Listes et dictionnaires →