Les Fonctions

Des blocs de code réutilisables. Comme des recettes de cuisine.

La machine à fonction

Une fonction prend une entrée (l'argument), la transforme, et renvoie une sortie. Change x et lance le calcul de f(x) = 2x + 1.

entrée x 3 ⚙️ f(x)=2x+1 sortie 7 3 f(3) = 7
x = 3

C'est quoi une fonction ?

📦 Fonction = Methode

On dit aussi "méthode" quand la fonction appartient à un objet/classe. C'est la meme chose : un bloc de code reutilisable !

Une fonction c'est comme une recette de cuisine :

📥 Ingredients
🍳 Recette
📤 Plat fini

Tu donnes des parametres (entrees), la fonction execute des instructions, et te renvoie un resultat.

🎯
1 fonction = 1 tache
Chaque fonction fait UNE seule chose bien
🔗
Elles s'appellent entre elles
Une fonction peut appeler d'autres fonctions
📁
Plusieurs par fichier
Un fichier contient plusieurs fonctions
# Exemple : fichier calculatrice.py
def additionner(a, b): # Fonction 1
def multiplier(a, b): # Fonction 2
def calculer_total(prix, qte): # Fonction 3
sous_total = multiplier(prix, qte) # Appelle fonction 2 !
return additionner(sous_total, taxe) # Appelle fonction 1 !

Testeur de fonctions

Fonction : additionner(a, b) → renvoie a + b

8
additionner(5, 3) → 8
Voir le code Python
def additionner(a, b):
    return a + b

Definir une fonction

Creer une fonction reutilisable

# Definition
def saluer(nom):
    return f"Bonjour {nom} !"

# Appel
message = saluer("Alice")
print(message)  # "Bonjour Alice !"
// Definition
function saluer(nom) {
    return `Bonjour ${nom} !`;
}

// Appel
const message = saluer("Alice");
console.log(message);  // "Bonjour Alice !"
// Definition (dans une classe)
public static String saluer(String nom) {
    return "Bonjour " + nom + " !";
}

// Appel
String message = saluer("Alice");
System.out.println(message);  // "Bonjour Alice !"
// Definition
static string Saluer(string nom) {
    return $"Bonjour {nom} !";
}

// Appel
string message = Saluer("Alice");
Console.WriteLine(message);  // "Bonjour Alice !"
// Definition
std::string saluer(std::string nom) {
    return "Bonjour " + nom + " !";
}

// Appel
std::string message = saluer("Alice");
std::cout << message << std::endl;  // "Bonjour Alice !"
# Definition avec function()
saluer <- function(nom) {
    paste("Bonjour", nom, "!")
}

# Appel
message <- saluer("Alice")
print(message)  # "Bonjour Alice !"

# R retourne la derniere expression auto !
carre <- function(x) x^2  # Une ligne

Parametres & Return

📥 Parametres

Les valeurs qu'on donne a la fonction

calculer(prix, taxe)
📤 Return

La valeur que la fonction renvoie

return prix * taxe
# Plusieurs parametres
def calculer_prix(prix, quantite, remise):
    total = prix * quantite
    reduction = total * remise
    return total - reduction

# Utilisation
final = calculer_prix(100, 3, 0.1)
print(final)  # 270.0
// Plusieurs parametres
function calculerPrix(prix, quantite, remise) {
    const total = prix * quantite;
    const reduction = total * remise;
    return total - reduction;
}

// Utilisation
const final = calculerPrix(100, 3, 0.1);
console.log(final);  // 270
// Plusieurs parametres
static double calculerPrix(double prix, int quantite, double remise) {
    double total = prix * quantite;
    double reduction = total * remise;
    return total - reduction;
}

// Utilisation
double finalPrice = calculerPrix(100, 3, 0.1);
System.out.println(finalPrice);  // 270.0

Parametres par defaut

Valeurs utilisees si aucun argument n'est fourni

🎮 Testeur interactif

def commander_pizza(taille="medium", extra_fromage=False):
    prix = {"small": 8, "medium": 12, "large": 16}
    total = prix[taille]
    if extra_fromage:
        total += 2
    return total
Resultat :
🍕
12 CHF
Medium, sans extra
# Parametres par defaut = valeur si non fourni
def saluer(nom, langue="fr", formel=False):
    if langue == "fr":
        salut = "Bonjour" if formel else "Salut"
    else:
        salut = "Good day" if formel else "Hi"
    return f"{salut} {nom} !"

# Differentes facons d'appeler :
saluer("Alice")                    # Salut Alice ! (defauts: fr, informel)
saluer("Bob", "en")               # Hi Bob ! (anglais, informel)
saluer("Marie", "fr", True)      # Bonjour Marie ! (francais, formel)
saluer("John", formel=True)       # Bonjour John ! (argument nomme)
// Parametres par defaut avec =
function saluer(nom, langue = "fr", formel = false) {
    let salut;
    if (langue === "fr") {
        salut = formel ? "Bonjour" : "Salut";
    } else {
        salut = formel ? "Good day" : "Hi";
    }
    return `${salut} ${nom} !`;
}

// Differentes facons d'appeler :
saluer("Alice");                   // Salut Alice !
saluer("Bob", "en");              // Hi Bob !
saluer("Marie", "fr", true);     // Bonjour Marie !
// Java n'a PAS de parametres par defaut !
// On utilise la SURCHARGE (overloading) :

static String saluer(String nom) {
    return saluer(nom, "fr", false);  // Appelle la version complete
}

static String saluer(String nom, String langue) {
    return saluer(nom, langue, false);
}

static String saluer(String nom, String langue, boolean formel) {
    String salut = langue.equals("fr")
        ? (formel ? "Bonjour" : "Salut")
        : (formel ? "Good day" : "Hi");
    return salut + " " + nom + " !";
}

// Java choisit automatiquement la bonne version !
saluer("Alice");                   // → version 1 param
saluer("Bob", "en");              // → version 2 params
saluer("Marie", "fr", true);     // → version 3 params

💡 Regle : Les parametres avec defaut doivent etre a la fin !
def fn(a, b=1, c=2) ✅ OK
def fn(a=1, b, c) ❌ Erreur !

Surcharge de fonctions

Plusieurs versions d'une meme fonction avec des parametres differents

🎯 Comment ca marche ?

aire(cote)
Carre : cote²
aire(long, larg)
Rectangle : L × l
aire(base, h, "tri")
Triangle : b×h/2
Le programme choisit automatiquement la bonne version selon les parametres !

🧮 Calculateur d'aire interactif

aire(5)
Aire =
25
# Python : parametres optionnels + logique
def aire(a, b=None, forme="rect"):
    if b is None:
        return a * a                    # Carre
    elif forme == "tri":
        return (a * b) / 2             # Triangle
    else:
        return a * b                    # Rectangle

# Utilisation :
aire(5)                  # 25 (carre 5x5)
aire(4, 6)               # 24 (rectangle 4x6)
aire(4, 6, "tri")        # 12 (triangle base=4, h=6)
// JavaScript : parametres par defaut
function aire(a, b = null, forme = "rect") {
    if (b === null) {
        return a * a;                   // Carre
    } else if (forme === "tri") {
        return (a * b) / 2;            // Triangle
    } else {
        return a * b;                   // Rectangle
    }
}

// Utilisation :
aire(5);                 // 25 (carre)
aire(4, 6);              // 24 (rectangle)
aire(4, 6, "tri");       // 12 (triangle)
// Java : VRAIE surcharge (plusieurs methodes)
static double aire(double cote) {
    return cote * cote;              // Carre
}

static double aire(double longueur, double largeur) {
    return longueur * largeur;       // Rectangle
}

static double aire(double base, double hauteur, String type) {
    if (type.equals("triangle")) {
        return (base * hauteur) / 2;
    }
    return base * hauteur;
}

// Java choisit la bonne methode selon les arguments !
aire(5);                           // → version 1 param
aire(4, 6);                        // → version 2 params
aire(4, 6, "triangle");           // → version 3 params

⚠️ Attention : Python et JavaScript n'ont pas de vraie surcharge. On simule avec des parametres optionnels. Seuls Java, C#, C++ ont une vraie surcharge.

La portee (Scope)

Ou une variable est accessible - concept TRES important !

🏠 Analogie : La maison

🌍 GLOBAL = Le jardin

Visible par tout le monde, de partout dans la maison.

nom_app = "Mukbang"
🚪 LOCAL = Ta chambre

Visible seulement quand tu es DANS la chambre.

secret = "mon mot de passe"

🎮 Visualiseur de scope

🌍 Scope GLOBAL
app = "Mukbang" version = 2.0
🏠 fonction1()
x = 10 y = 20
🏠 fonction2()
a = "hello" b = [1,2,3]
Variables accessibles ici :
✓ app, version
🌍
Global
Declare hors de toute fonction. Accessible partout.
⚠️ A eviter si possible !
🏠
Local (fonction)
Declare dans une fonction. Meurt a la fin de la fonction.
✓ Recommande !
📦
Block (JS)
Dans un if/for avec let/const. Meurt a la fin du bloc.
let/const vs var
app = "Mukbang"  # Variable GLOBALE

def fonction1():
    x = 10   # Variable LOCALE
    print(app)  # ✓ OK : app est global
    print(x)    # ✓ OK : x est local ici

def fonction2():
    y = 20
    print(app)  # ✓ OK : app est global
    print(x)    # ✗ ERREUR : x n'existe pas ici !

fonction1()
print(app)  # ✓ OK
print(x)    # ✗ ERREUR : x est morte avec fonction1
const app = "Mukbang";  // Variable GLOBALE

function fonction1() {
    let x = 10;   // Variable LOCALE
    console.log(app);  // ✓ OK : app est global
    console.log(x);    // ✓ OK : x est local ici
}

function fonction2() {
    let y = 20;
    console.log(app);  // ✓ OK : app est global
    console.log(x);    // ✗ ERREUR : x n'existe pas ici !
}

fonction1();
console.log(app);  // ✓ OK
console.log(x);    // ✗ ERREUR : x est morte avec fonction1

👤 Shadowing (meme nom, differentes variables)

Si une variable locale a le meme nom qu'une globale, la locale "cache" la globale !

x = 100  # Variable globale

def test():
    x = 5  # Nouvelle variable LOCALE (shadow)
    print(x)  # Affiche 5 (la locale)

test()
print(x)  # Affiche 100 (la globale intacte !)

⚠️ Modifier une variable globale (a eviter !)

Pourquoi c'est dangereux ?
  • 🐛 Bugs difficiles : N'importe quelle fonction peut modifier la variable → impossible de savoir QUI l'a changee
  • 🔄 Effets de bord : La fonction fait des choses "en cachette" en plus de sa tache principale
  • 🧪 Tests impossibles : Tu ne peux pas tester la fonction isolement, elle depend d'un etat externe
  • 👥 Travail en equipe : Quelqu'un modifie la globale ailleurs → ton code casse mysterieusement
✅ Regle d'or : Une fonction recoit des parametres et retourne un resultat. C'est tout !
Python : mot-cle global
compteur = 0

def incrementer():
    global compteur
    compteur += 1

incrementer()
print(compteur)  # 1
Meilleure solution : parametres !
def incrementer(n):
    return n + 1

compteur = 0
compteur = incrementer(compteur)
print(compteur)  # 1

📦 Block Scope (JavaScript seulement)

En JS, let et const sont limites au bloc {}, mais var ignore les blocs !

if (true) {
    let a = 1;    // Scope = ce bloc
    var b = 2;    // Scope = fonction entiere !
    const c = 3;  // Scope = ce bloc
}

console.log(a);  // ✗ ERREUR : a n'existe plus
console.log(b);  // ✓ OK : b existe encore (var)
console.log(c);  // ✗ ERREUR : c n'existe plus
✓ Utilise toujours let et const ✗ Evite var

Fonctions flechees / Lambda

Syntaxe courte pour des fonctions simples

# Fonction classique
def doubler(x):
    return x * 2

# Lambda equivalente
doubler = lambda x: x * 2

print(doubler(5))  # 10

# Utile avec map, filter...
nombres = [1, 2, 3, 4]
doubles = list(map(lambda x: x * 2, nombres))
# [2, 4, 6, 8]
// Fonction classique
function doubler(x) {
    return x * 2;
}

// Arrow function equivalente
const doubler = (x) => x * 2;

console.log(doubler(5));  // 10

// Utile avec map, filter...
const nombres = [1, 2, 3, 4];
const doubles = nombres.map(x => x * 2);
// [2, 4, 6, 8]
// Java 8+ avec lambdas
List<Integer> nombres = Arrays.asList(1, 2, 3, 4);

// Lambda avec Stream API
List<Integer> doubles = nombres.stream()
    .map(x -> x * 2)  // Lambda
    .collect(Collectors.toList());
// [2, 4, 6, 8]

// Interface fonctionnelle
Function<Integer, Integer> doubler = x -> x * 2;
doubler.apply(5);  // 10
// C# avec lambdas
var nombres = new List<int> { 1, 2, 3, 4 };

// Lambda avec LINQ
var doubles = nombres.Select(x => x * 2).ToList();
// [2, 4, 6, 8]

// Func delegate
Func<int, int> doubler = x => x * 2;
doubler(5);  // 10

Fonctions sans return

Parfois on veut juste executer des actions sans renvoyer de valeur

✅ AVEC return
La fonction calcule et renvoie un resultat
🔢 Calculer : calculer_moyenne(notes)
🔄 Transformer : convertir_euros(chf)
Verifier : est_majeur(age)
🔍 Chercher : trouver_max(liste)
Usage : resultat = ma_fonction(x)
🚫 SANS return
La fonction fait une action, l'effet EST le but
🖥️ Afficher : afficher_menu()
💾 Sauvegarder : enregistrer_score(pts)
📡 Envoyer : envoyer_email(dest)
🎮 Modifier : deplacer_joueur(x, y)
Usage : ma_fonction(x) (pas de =)
🤔 LA question a te poser :
"Est-ce que j'ai besoin du resultat APRES l'appel ?"
✅ OUI
→ return
prix = calculer_prix(qte)
if est_valide(email):
max = trouver_max(liste)
❌ NON
→ pas de return
afficher_menu()
sauvegarder(data)
jouer_son("ding")
🎯 Regarde comment tu APPELLES ta fonction :
x = fonction() → besoin du resultat → return
fonction() tout seul → juste l'action → pas de return
def afficher_menu():
    print("=== MENU ===")
    print("1. Jouer")
    print("2. Options")
    print("3. Quitter")
    # Pas de return

afficher_menu()  # Affiche le menu
function afficherMenu() {
    console.log("=== MENU ===");
    console.log("1. Jouer");
    console.log("2. Options");
    console.log("3. Quitter");
    // Pas de return (retourne undefined)
}

afficherMenu();  // Affiche le menu
// void = pas de retour
static void afficherMenu() {
    System.out.println("=== MENU ===");
    System.out.println("1. Jouer");
    System.out.println("2. Options");
    System.out.println("3. Quitter");
}

afficherMenu();  // Affiche le menu

Exemple pratique : Calculatrice

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

def soustraire(a, b):
    return a - b

def multiplier(a, b):
    return a * b

def diviser(a, b):
    if b == 0:
        return "Erreur: division par zero"
    return a / b

def calculer(a, op, b):
    if op == "+":
        return additionner(a, b)
    elif op == "-":
        return soustraire(a, b)
    elif op == "*":
        return multiplier(a, b)
    elif op == "/":
        return diviser(a, b)

print(calculer(10, "+", 5))  # 15
print(calculer(10, "/", 3))  # 3.333...
const additionner = (a, b) => a + b;
const soustraire = (a, b) => a - b;
const multiplier = (a, b) => a * b;
const diviser = (a, b) => b === 0 ? "Erreur" : a / b;

function calculer(a, op, b) {
    const operations = {
        "+": additionner,
        "-": soustraire,
        "*": multiplier,
        "/": diviser
    };
    return operations[op]?.(a, b) ?? "Operation inconnue";
}

console.log(calculer(10, "+", 5));  // 15
console.log(calculer(10, "/", 3));  // 3.333...

🪆 Récursivité : Une fonction qui s'appelle elle-même

Une fonction récursive est une fonction qui s'appelle elle-même pour résoudre un problème. C'est comme des poupées russes 🪆 : chaque poupée contient une version plus petite d'elle-même !

🪞 Analogie : Les miroirs infinis

🪞🪞🪞

Deux miroirs face à face créent des reflets infinis...

🛑

...mais il faut un cas de base pour s'arrêter !

📐 Structure d'une fonction récursive

🛑 Cas de base (arrêt)

La condition qui STOPPE la récursion. Sans ça = boucle infinie !

🔄 Cas récursif

La fonction s'appelle elle-même avec un problème PLUS PETIT.

🧮 Exemple : Factorielle (n!)

5! = 5 × 4 × 3 × 2 × 1 = 120
Mais aussi : 5! = 5 × 4! (récursif !)

def factorielle(n):
    # 🛑 Cas de base
    if n <= 1:
        return 1

    # 🔄 Cas récursif
    return n * factorielle(n - 1)

print(factorielle(5))  # 120
function factorielle(n) {
    // 🛑 Cas de base
    if (n <= 1) {
        return 1;
    }

    // 🔄 Cas récursif
    return n * factorielle(n - 1);
}

console.log(factorielle(5));  // 120

📚 Visualisation : La pile d'appels

Quand tu appelles factorielle(4), voici ce qui se passe :

factorielle(4) → attend factorielle(3)
factorielle(3) → attend factorielle(2)
factorielle(2) → attend factorielle(1)
factorielle(1) → retourne 1 🛑
↑ Puis tout remonte ! 2×1=2, 3×2=6, 4×6=24

🎮 Essaie toi-même

= ?

⚠️ Attention : Sans cas de base ou si le problème ne "rétrécit" pas, tu obtiens une récursion infinieStack Overflow (dépassement de pile) !

💡 Quand utiliser la récursivité ?
• Structures arborescentes (dossiers, DOM, JSON)
• Algorithmes de tri (quicksort, mergesort)
• Problèmes "diviser pour régner"
• Parcours de graphes

📋 Recapitulatif

def / function
Definir une fonction
return
Renvoyer une valeur
Parametres
Entrees de la fonction
Scope
Portee des variables
Récursivité
Fonction qui s'appelle elle-même
Cas de base
Condition d'arrêt récursif
🎯

Quiz Mode Survie

1 erreur = Game Over
📦

Les Fonctions

10 questions aleatoires - Mode Survie

Prog 4 Prog 6
🎬

Pour aller plus loin

Les excellentes vidéos de Graven sur les fonctions :

Java Fonctions
Apprendre le Java #6 - Les Fonctions
Graven • ☕ Java
Python Fonctions
Apprendre le Python #6 - Les Fonctions
Graven • 🐍 Python
Glisser pour continuer vers Prog 6 : Tableaux & Listes
⬇️
Intermédiaire