{
  "chapter": {
    "id": "python-fonctions",
    "level": "snt",
    "theme": "Programmation",
    "title": "7. Fonctions",
    "description": "Définir une fonction avec def, l'appeler ; paramètres et arguments ;\nla valeur renvoyée par return, à distinguer d'un affichage par\nprint ; une fonction sans return renvoie None ; réutiliser un\nrésultat dans un calcul ou un test ; les variables locales.",
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "appel",
        "return"
      ],
      "title": "Appeler une fonction",
      "statement": "```python\ndef double(x):\n    return 2 * x\nprint(double(7))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`14`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel `double(7)` exécute la fonction avec `x`\négal à 7 et renvoie 14, que `print` affiche.\n"
        },
        {
          "text": "`2 * x`",
          "correct": false,
          "feedback": "Erreur : `return` renvoie le résultat du calcul, pas le texte de\nla formule.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : 7 est l'argument. La fonction renvoie 2 fois sa valeur.\n"
        },
        {
          "text": "Rien, une fonction n'affiche pas",
          "correct": false,
          "feedback": "Erreur : la fonction n'affiche rien, mais `print` affiche la\nvaleur qu'elle renvoie.\n"
        }
      ],
      "explanation": "Appeler une fonction, c'est exécuter son bloc avec les arguments\nfournis. La valeur qui suit `return` remplace l'appel dans\nl'expression, ici dans `print`.",
      "variants": [
        {
          "statement": "```python\ndef double(x):\n    return 2 * x\nprint(double(7))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`14`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `double(7)` exécute la fonction avec `x`\négal à 7 et renvoie 14, que `print` affiche.\n"
            },
            {
              "text": "`2 * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas le texte de\nla formule.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est l'argument. La fonction renvoie 2 fois sa valeur.\n"
            },
            {
              "text": "Rien, une fonction n'affiche pas",
              "correct": false,
              "feedback": "Erreur : la fonction n'affiche rien, mais `print` affiche la\nvaleur qu'elle renvoie.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est exécuter son bloc avec les arguments\nfournis. La valeur qui suit `return` remplace l'appel dans\nl'expression, ici dans `print`."
        },
        {
          "statement": "```python\ndef triple(x):\n    return 3 * x\nprint(triple(5))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`15`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `triple(5)` exécute la fonction avec `x`\négal à 5 et renvoie 15, que `print` affiche.\n"
            },
            {
              "text": "`3 * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas le texte de\nla formule.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est l'argument. La fonction renvoie 3 fois sa valeur.\n"
            },
            {
              "text": "Rien, une fonction n'affiche pas",
              "correct": false,
              "feedback": "Erreur : la fonction n'affiche rien, mais `print` affiche la\nvaleur qu'elle renvoie.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est exécuter son bloc avec les arguments\nfournis. La valeur qui suit `return` remplace l'appel dans\nl'expression, ici dans `print`."
        },
        {
          "statement": "```python\ndef double(x):\n    return 2 * x\nprint(double(11))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`22`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `double(11)` exécute la fonction avec `x`\négal à 11 et renvoie 22, que `print` affiche.\n"
            },
            {
              "text": "`2 * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas le texte de\nla formule.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : 11 est l'argument. La fonction renvoie 2 fois sa valeur.\n"
            },
            {
              "text": "Rien, une fonction n'affiche pas",
              "correct": false,
              "feedback": "Erreur : la fonction n'affiche rien, mais `print` affiche la\nvaleur qu'elle renvoie.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est exécuter son bloc avec les arguments\nfournis. La valeur qui suit `return` remplace l'appel dans\nl'expression, ici dans `print`."
        }
      ]
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "fonction",
        "parametres",
        "arguments"
      ],
      "title": "Paramètre et argument",
      "statement": "Une fonction est définie par `def aire(largeur, hauteur):` et\nappelée par `aire(4, 3)`. Que représente le 4 ?",
      "options": [
        {
          "text": "L'argument transmis au paramètre `largeur`",
          "correct": true,
          "feedback": "Bonne réponse : les arguments sont associés aux paramètres dans\nl'ordre. `largeur` vaut 4 et `hauteur` vaut 3 pendant l'appel.\n"
        },
        {
          "text": "Le nom du premier paramètre de la fonction",
          "correct": false,
          "feedback": "Erreur : le nom du paramètre est `largeur`. 4 est la valeur\nqu'il reçoit lors de cet appel.\n"
        },
        {
          "text": "La valeur renvoyée par la fonction",
          "correct": false,
          "feedback": "Erreur : la valeur renvoyée est calculée par la fonction, ici\nprobablement 12.\n"
        },
        {
          "text": "La valeur du paramètre `hauteur`",
          "correct": false,
          "feedback": "Erreur : l'ordre compte, le premier argument va au premier\nparamètre.\n"
        }
      ],
      "explanation": "Les paramètres sont les noms écrits dans la définition ; les\narguments sont les valeurs fournies à l'appel. Ils sont associés\ndans l'ordre."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "fonction",
        "definition",
        "appel"
      ],
      "title": "Définir sans appeler",
      "statement": "```python\ndef saluer():\n    print(\"Bonjour\")\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "Rien, la fonction n'est jamais appelée",
          "correct": true,
          "feedback": "Bonne réponse : `def` prépare la fonction sans l'exécuter. Il\nfaudrait ajouter la ligne `saluer()`.\n"
        },
        {
          "text": "`Bonjour`, une seule fois, à la définition",
          "correct": false,
          "feedback": "Erreur : le bloc d'une fonction ne s'exécute qu'à l'appel, et\naucun appel n'est écrit.\n"
        },
        {
          "text": "`Bonjour` sans fin, la fonction se relance",
          "correct": false,
          "feedback": "Erreur : une fonction n'est pas une boucle, et elle n'est même\npas appelée.\n"
        },
        {
          "text": "Une erreur, il manque `return` à la fonction",
          "correct": false,
          "feedback": "Erreur : `return` n'est pas obligatoire. Une fonction peut se\ncontenter d'afficher.\n"
        }
      ],
      "explanation": "Définir une fonction ne l'exécute pas. Le bloc ne tourne qu'au moment\nde l'appel, écrit avec le nom suivi de parenthèses."
    },
    {
      "id": "q04",
      "difficulty": 2,
      "skills": [
        "retour",
        "print",
        "none"
      ],
      "title": "Afficher n'est pas renvoyer",
      "statement": "```python\ndef carre(n):\n    print(n * n)\n\nr = carre(3)\nprint(r)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`9` puis `None`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel affiche 9, mais sans `return` la\nfonction renvoie `None`, qui est rangé dans `r` puis affiché.\n"
        },
        {
          "text": "`9` puis `9`",
          "correct": false,
          "feedback": "Erreur : `print` dans la fonction affiche, il ne renvoie rien.\n`r` ne reçoit pas 9.\n"
        },
        {
          "text": "`None` puis `9`",
          "correct": false,
          "feedback": "Erreur : l'affichage de 9 a lieu pendant l'appel, donc avant le\nsecond `print`.\n"
        },
        {
          "text": "`9` seulement",
          "correct": false,
          "feedback": "Erreur : le second `print` affiche bien quelque chose, la valeur\n`None`.\n"
        }
      ],
      "explanation": "`print` montre une valeur à l'écran, `return` la transmet au\nprogramme. Une fonction sans `return` renvoie `None`, et son\nrésultat ne peut pas être réutilisé."
    },
    {
      "id": "q05",
      "difficulty": 2,
      "skills": [
        "return",
        "reutilisation"
      ],
      "title": "Réutiliser un résultat",
      "statement": "```python\ndef prix_ttc(ht):\n    return ht * 1.2\ntotal = prix_ttc(10) + prix_ttc(20)\nprint(total)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`36.0`",
          "correct": true,
          "feedback": "Bonne réponse : les deux appels renvoient 12.0 et 24.0, dont la\nsomme est 36.0.\n"
        },
        {
          "text": "`36`",
          "correct": false,
          "feedback": "Erreur : la multiplication par 1.2 donne des flottants, la somme\nest affichée `36.0`.\n"
        },
        {
          "text": "`30`",
          "correct": false,
          "feedback": "Erreur : 30 est la somme des prix hors taxe, avant la\nmultiplication.\n"
        },
        {
          "text": "`12.0`",
          "correct": false,
          "feedback": "Erreur : 12.0 n'est que le premier appel, le second est ajouté.\n"
        }
      ],
      "explanation": "Une valeur renvoyée s'utilise comme n'importe quelle valeur : dans\nune addition, une affectation ou un autre appel. C'est ce qui rend\n`return` plus puissant que `print`.",
      "variants": [
        {
          "statement": "```python\ndef prix_ttc(ht):\n    return ht * 1.2\ntotal = prix_ttc(10) + prix_ttc(20)\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`36.0`",
              "correct": true,
              "feedback": "Bonne réponse : les deux appels renvoient 12.0 et 24.0, dont la\nsomme est 36.0.\n"
            },
            {
              "text": "`36`",
              "correct": false,
              "feedback": "Erreur : la multiplication par 1.2 donne des flottants, la somme\nest affichée `36.0`.\n"
            },
            {
              "text": "`30`",
              "correct": false,
              "feedback": "Erreur : 30 est la somme des prix hors taxe, avant la\nmultiplication.\n"
            },
            {
              "text": "`12.0`",
              "correct": false,
              "feedback": "Erreur : 12.0 n'est que le premier appel, le second est ajouté.\n"
            }
          ],
          "explanation": "Une valeur renvoyée s'utilise comme n'importe quelle valeur : dans\nune addition, une affectation ou un autre appel. C'est ce qui rend\n`return` plus puissant que `print`."
        },
        {
          "statement": "```python\ndef prix_ttc(ht):\n    return ht * 1.2\ntotal = prix_ttc(15) + prix_ttc(25)\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`48.0`",
              "correct": true,
              "feedback": "Bonne réponse : les deux appels renvoient 18.0 et 30.0, dont la\nsomme est 48.0.\n"
            },
            {
              "text": "`48`",
              "correct": false,
              "feedback": "Erreur : la multiplication par 1.2 donne des flottants, la somme\nest affichée `48.0`.\n"
            },
            {
              "text": "`40`",
              "correct": false,
              "feedback": "Erreur : 40 est la somme des prix hors taxe, avant la\nmultiplication.\n"
            },
            {
              "text": "`18.0`",
              "correct": false,
              "feedback": "Erreur : 18.0 n'est que le premier appel, le second est ajouté.\n"
            }
          ],
          "explanation": "Une valeur renvoyée s'utilise comme n'importe quelle valeur : dans\nune addition, une affectation ou un autre appel. C'est ce qui rend\n`return` plus puissant que `print`."
        },
        {
          "statement": "```python\ndef prix_ttc(ht):\n    return ht * 1.2\ntotal = prix_ttc(5) + prix_ttc(30)\nprint(total)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`42.0`",
              "correct": true,
              "feedback": "Bonne réponse : les deux appels renvoient 6.0 et 36.0, dont la\nsomme est 42.0.\n"
            },
            {
              "text": "`42`",
              "correct": false,
              "feedback": "Erreur : la multiplication par 1.2 donne des flottants, la somme\nest affichée `42.0`.\n"
            },
            {
              "text": "`35`",
              "correct": false,
              "feedback": "Erreur : 35 est la somme des prix hors taxe, avant la\nmultiplication.\n"
            },
            {
              "text": "`6.0`",
              "correct": false,
              "feedback": "Erreur : 6.0 n'est que le premier appel, le second est ajouté.\n"
            }
          ],
          "explanation": "Une valeur renvoyée s'utilise comme n'importe quelle valeur : dans\nune addition, une affectation ou un autre appel. C'est ce qui rend\n`return` plus puissant que `print`."
        }
      ]
    },
    {
      "id": "q06",
      "difficulty": 2,
      "skills": [
        "parametres",
        "ordre"
      ],
      "title": "Deux paramètres, un ordre",
      "statement": "```python\ndef soustraire(a, b):\n    return a - b\nprint(soustraire(3, 10))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`-7`",
          "correct": true,
          "feedback": "Bonne réponse : `a` vaut 3 et `b` vaut 10, la fonction renvoie\n3 moins 10.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : l'ordre des arguments compte, le premier va dans `a`.\n"
        },
        {
          "text": "`13`",
          "correct": false,
          "feedback": "Erreur : la fonction soustrait, elle n'additionne pas.\n"
        },
        {
          "text": "Une erreur, le résultat est négatif",
          "correct": false,
          "feedback": "Erreur : un résultat négatif est un entier comme un autre.\n"
        }
      ],
      "explanation": "Les arguments sont affectés aux paramètres dans l'ordre de l'appel.\nInverser deux arguments change le résultat sans provoquer d'erreur,\nd'où l'importance de l'ordre.",
      "variants": [
        {
          "statement": "```python\ndef soustraire(a, b):\n    return a - b\nprint(soustraire(3, 10))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-7`",
              "correct": true,
              "feedback": "Bonne réponse : `a` vaut 3 et `b` vaut 10, la fonction renvoie\n3 moins 10.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : l'ordre des arguments compte, le premier va dans `a`.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : la fonction soustrait, elle n'additionne pas.\n"
            },
            {
              "text": "Une erreur, le résultat est négatif",
              "correct": false,
              "feedback": "Erreur : un résultat négatif est un entier comme un autre.\n"
            }
          ],
          "explanation": "Les arguments sont affectés aux paramètres dans l'ordre de l'appel.\nInverser deux arguments change le résultat sans provoquer d'erreur,\nd'où l'importance de l'ordre."
        },
        {
          "statement": "```python\ndef soustraire(a, b):\n    return a - b\nprint(soustraire(4, 9))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-5`",
              "correct": true,
              "feedback": "Bonne réponse : `a` vaut 4 et `b` vaut 9, la fonction renvoie\n4 moins 9.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : l'ordre des arguments compte, le premier va dans `a`.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : la fonction soustrait, elle n'additionne pas.\n"
            },
            {
              "text": "Une erreur, le résultat est négatif",
              "correct": false,
              "feedback": "Erreur : un résultat négatif est un entier comme un autre.\n"
            }
          ],
          "explanation": "Les arguments sont affectés aux paramètres dans l'ordre de l'appel.\nInverser deux arguments change le résultat sans provoquer d'erreur,\nd'où l'importance de l'ordre."
        },
        {
          "statement": "```python\ndef soustraire(a, b):\n    return a - b\nprint(soustraire(2, 15))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`-13`",
              "correct": true,
              "feedback": "Bonne réponse : `a` vaut 2 et `b` vaut 15, la fonction renvoie\n2 moins 15.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : l'ordre des arguments compte, le premier va dans `a`.\n"
            },
            {
              "text": "`17`",
              "correct": false,
              "feedback": "Erreur : la fonction soustrait, elle n'additionne pas.\n"
            },
            {
              "text": "Une erreur, le résultat est négatif",
              "correct": false,
              "feedback": "Erreur : un résultat négatif est un entier comme un autre.\n"
            }
          ],
          "explanation": "Les arguments sont affectés aux paramètres dans l'ordre de l'appel.\nInverser deux arguments change le résultat sans provoquer d'erreur,\nd'où l'importance de l'ordre."
        }
      ]
    },
    {
      "id": "q07",
      "difficulty": 2,
      "skills": [
        "retour",
        "trace"
      ],
      "title": "Ce qui suit return",
      "statement": "```python\ndef test(x):\n    return x + 1\n    print(\"Après\")\n\nprint(test(1))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`2` seulement",
          "correct": true,
          "feedback": "Bonne réponse : `return` termine immédiatement la fonction. La\nligne qui suit n'est jamais exécutée.\n"
        },
        {
          "text": "`Après` puis `2`",
          "correct": false,
          "feedback": "Erreur : la fonction s'arrête au `return`, avant le `print`.\n"
        },
        {
          "text": "`2` puis `Après`",
          "correct": false,
          "feedback": "Erreur : après un `return`, plus rien ne s'exécute dans la\nfonction.\n"
        },
        {
          "text": "`Après` seulement",
          "correct": false,
          "feedback": "Erreur : l'appel renvoie 2, que `print` affiche, et `Après`\nn'est jamais atteint.\n"
        }
      ],
      "explanation": "`return` renvoie une valeur et quitte la fonction sur-le-champ. Du\ncode écrit après un `return` inconditionnel est du code mort."
    },
    {
      "id": "q08",
      "difficulty": 2,
      "skills": [
        "fonction",
        "booleens",
        "retour"
      ],
      "title": "Une fonction qui répond par oui ou non",
      "statement": "```python\ndef est_majeur(age):\n    return age >= 18\n\nprint(est_majeur(20), est_majeur(12))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`True False`",
          "correct": true,
          "feedback": "Bonne réponse : la fonction renvoie le résultat de la\ncomparaison, vrai pour 20 et faux pour 12.\n"
        },
        {
          "text": "`False True`",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse, 20 est supérieur ou égal à 18.\n"
        },
        {
          "text": "`True True`",
          "correct": false,
          "feedback": "Erreur : 12 n'est pas supérieur ou égal à 18.\n"
        },
        {
          "text": "`20 12`",
          "correct": false,
          "feedback": "Erreur : la fonction ne renvoie pas l'âge mais un booléen.\n"
        }
      ],
      "explanation": "Une fonction peut renvoyer directement une comparaison. Elle sert\nalors de test réutilisable, par exemple dans un `if`."
    },
    {
      "id": "q09",
      "difficulty": 3,
      "skills": [
        "variables-locales",
        "fonction",
        "erreur"
      ],
      "title": "Une variable locale",
      "statement": "```python\ndef calcul():\n    resultat = 10\n    return resultat\n\ncalcul()\nprint(resultat)\n```\n\nQue se passe-t-il ?",
      "options": [
        {
          "text": "Une erreur, `resultat` n'existe que dans la fonction",
          "correct": true,
          "feedback": "Bonne réponse : `resultat` est une variable locale, créée à\nl'appel et détruite à la sortie. En dehors, elle n'existe pas.\n"
        },
        {
          "text": "Python affiche 10, la valeur renvoyée par l'appel",
          "correct": false,
          "feedback": "Erreur : pour obtenir 10, il faudrait écrire\n`print(calcul())`, ou ranger la valeur renvoyée dans une\nvariable.\n"
        },
        {
          "text": "Python affiche `None`, faute de valeur conservée",
          "correct": false,
          "feedback": "Erreur : la fonction renvoie bien 10, mais ce résultat n'est pas\nconservé, et `resultat` est inconnu à l'extérieur.\n"
        },
        {
          "text": "Python affiche le mot `resultat`, sans sa valeur",
          "correct": false,
          "feedback": "Erreur : `print` affiche la valeur d'une variable, et ici la\nvariable n'existe pas.\n"
        }
      ],
      "explanation": "Les variables créées dans une fonction sont locales : elles\ndisparaissent à la fin de l'appel. Pour transmettre une valeur à\nl'extérieur, on utilise `return`."
    },
    {
      "id": "q10",
      "difficulty": 2,
      "skills": [
        "appel",
        "arguments",
        "erreur"
      ],
      "title": "Trop d'arguments",
      "statement": "```python\ndef moyenne(a, b):\n    return (a + b) / 2\n\nprint(moyenne(10, 12, 14))\n```\n\nQue se passe-t-il ?",
      "options": [
        {
          "text": "Une erreur, la fonction attend deux arguments et en reçoit trois",
          "correct": true,
          "feedback": "Bonne réponse : le nombre d'arguments doit correspondre au\nnombre de paramètres. Python signale une `TypeError`.\n"
        },
        {
          "text": "Python affiche 12.0, la moyenne des trois valeurs",
          "correct": false,
          "feedback": "Erreur : la fonction ne sait calculer qu'avec deux valeurs,\nelle ne s'adapte pas.\n"
        },
        {
          "text": "Python affiche 11.0, le troisième argument est ignoré",
          "correct": false,
          "feedback": "Erreur : Python n'ignore pas un argument en trop, il refuse\nl'appel.\n"
        },
        {
          "text": "Python affiche 13.0, à partir des deux derniers arguments",
          "correct": false,
          "feedback": "Erreur : aucun choix n'est fait parmi les arguments, l'appel est\nrefusé.\n"
        }
      ],
      "explanation": "Un appel doit fournir exactement un argument par paramètre. En\ndonner trop ou trop peu déclenche une erreur `TypeError`, dont le\nmessage indique le nombre attendu."
    },
    {
      "id": "q11",
      "difficulty": 3,
      "skills": [
        "appel",
        "composition"
      ],
      "title": "Une fonction appelée dans une autre",
      "statement": "```python\ndef double(x):\n    return 2 * x\ndef quadruple(x):\n    return double(double(x))\nprint(quadruple(3))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`12`",
          "correct": true,
          "feedback": "Bonne réponse : `double(3)` vaut 6, et `double(6)` vaut 12.\n"
        },
        {
          "text": "`6`",
          "correct": false,
          "feedback": "Erreur : 6 est le résultat du premier `double`, auquel on\napplique encore `double`.\n"
        },
        {
          "text": "`24`",
          "correct": false,
          "feedback": "Erreur : deux multiplications par 2 font un facteur 4, pas 8.\n"
        },
        {
          "text": "`9`",
          "correct": false,
          "feedback": "Erreur : la fonction multiplie par 2, elle n'élève pas au carré.\n"
        }
      ],
      "explanation": "Une fonction peut en appeler une autre, y compris avec le résultat\nd'un premier appel comme argument. On évalue de l'intérieur vers\nl'extérieur.",
      "variants": [
        {
          "statement": "```python\ndef double(x):\n    return 2 * x\ndef quadruple(x):\n    return double(double(x))\nprint(quadruple(3))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`12`",
              "correct": true,
              "feedback": "Bonne réponse : `double(3)` vaut 6, et `double(6)` vaut 12.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est le résultat du premier `double`, auquel on\napplique encore `double`.\n"
            },
            {
              "text": "`24`",
              "correct": false,
              "feedback": "Erreur : deux multiplications par 2 font un facteur 4, pas 8.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie par 2, elle n'élève pas au carré.\n"
            }
          ],
          "explanation": "Une fonction peut en appeler une autre, y compris avec le résultat\nd'un premier appel comme argument. On évalue de l'intérieur vers\nl'extérieur."
        },
        {
          "statement": "```python\ndef triple(x):\n    return 3 * x\ndef fois_neuf(x):\n    return triple(triple(x))\nprint(fois_neuf(2))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`18`",
              "correct": true,
              "feedback": "Bonne réponse : `triple(2)` vaut 6, et `triple(6)` vaut 18.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est le résultat du premier `triple`, auquel on\napplique encore `triple`.\n"
            },
            {
              "text": "`54`",
              "correct": false,
              "feedback": "Erreur : deux multiplications par 3 font un facteur 9, pas 27.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie par 3, elle n'élève pas au carré.\n"
            }
          ],
          "explanation": "Une fonction peut en appeler une autre, y compris avec le résultat\nd'un premier appel comme argument. On évalue de l'intérieur vers\nl'extérieur."
        },
        {
          "statement": "```python\ndef double(x):\n    return 2 * x\ndef quadruple(x):\n    return double(double(x))\nprint(quadruple(5))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`20`",
              "correct": true,
              "feedback": "Bonne réponse : `double(5)` vaut 10, et `double(10)` vaut 20.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : 10 est le résultat du premier `double`, auquel on\napplique encore `double`.\n"
            },
            {
              "text": "`40`",
              "correct": false,
              "feedback": "Erreur : deux multiplications par 2 font un facteur 4, pas 8.\n"
            },
            {
              "text": "`25`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie par 2, elle n'élève pas au carré.\n"
            }
          ],
          "explanation": "Une fonction peut en appeler une autre, y compris avec le résultat\nd'un premier appel comme argument. On évalue de l'intérieur vers\nl'extérieur."
        }
      ]
    },
    {
      "id": "q12",
      "difficulty": 3,
      "skills": [
        "retour",
        "condition"
      ],
      "title": "Deux return dans une fonction",
      "statement": "```python\ndef categorie(age):\n    if age < 12:\n        return \"enfant\"\n    return \"adulte\"\n\nprint(categorie(9), categorie(30))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`enfant adulte`",
          "correct": true,
          "feedback": "Bonne réponse : pour 9, le premier `return` s'exécute et la\nfonction s'arrête ; pour 30, la condition est fausse et le\nsecond `return` est atteint.\n"
        },
        {
          "text": "`enfant enfant`",
          "correct": false,
          "feedback": "Erreur : pour 30, la condition `age < 12` est fausse.\n"
        },
        {
          "text": "`adulte adulte`",
          "correct": false,
          "feedback": "Erreur : pour 9, la condition est vraie et `enfant` est renvoyé\navant d'atteindre le second `return`.\n"
        },
        {
          "text": "Une erreur, une fonction n'a qu'un seul `return`",
          "correct": false,
          "feedback": "Erreur : une fonction peut contenir plusieurs `return`. Le\npremier atteint termine l'appel.\n"
        }
      ],
      "explanation": "Plusieurs `return` peuvent figurer dans une fonction ; seul le\npremier rencontré s'exécute. Un `return` dans un `if` évite parfois\nun `else`."
    },
    {
      "id": "q13",
      "difficulty": 1,
      "skills": [
        "fonction",
        "definition"
      ],
      "title": "Commencer une définition",
      "statement": "Quelle ligne commence correctement la définition d'une fonction\n`aire` à deux paramètres ?",
      "options": [
        {
          "text": "`def aire(l, h):`",
          "correct": true,
          "feedback": "Bonne réponse : le mot-clé `def`, le nom, les paramètres entre\nparenthèses et les deux-points.\n"
        },
        {
          "text": "`function aire(l, h):`",
          "correct": false,
          "feedback": "Erreur : `function` n'est pas un mot-clé de Python.\n"
        },
        {
          "text": "`def aire(l, h)`",
          "correct": false,
          "feedback": "Erreur : il manque les deux-points qui annoncent le bloc.\n"
        },
        {
          "text": "`aire(l, h) = def`",
          "correct": false,
          "feedback": "Erreur : `def` se place en tête de ligne, avant le nom.\n"
        }
      ],
      "explanation": "Une définition s'écrit `def nom(parametres):` suivie d'un bloc\nindenté. Les deux-points et l'indentation sont obligatoires, comme\npour `if` et `for`."
    },
    {
      "id": "q14",
      "difficulty": 2,
      "skills": [
        "appel",
        "composition"
      ],
      "title": "Un appel dans un appel",
      "statement": "```python\ndef suivant(n):\n    return n + 1\nprint(suivant(1), suivant(suivant(1)))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`2 3`",
          "correct": true,
          "feedback": "Bonne réponse : `suivant(1)` vaut 2, et `suivant(2)` vaut 3.\n"
        },
        {
          "text": "`2 2`",
          "correct": false,
          "feedback": "Erreur : le second appel reçoit 2 en argument, il renvoie 3.\n"
        },
        {
          "text": "`1 2`",
          "correct": false,
          "feedback": "Erreur : le premier appel renvoie déjà 2.\n"
        },
        {
          "text": "`3 3`",
          "correct": false,
          "feedback": "Erreur : le premier appel n'ajoute 1 qu'une fois.\n"
        }
      ],
      "explanation": "Chaque appel est indépendant et reçoit ses propres arguments. Quand\nun appel sert d'argument à un autre, on calcule d'abord le plus\nintérieur.",
      "variants": [
        {
          "statement": "```python\ndef suivant(n):\n    return n + 1\nprint(suivant(1), suivant(suivant(1)))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`2 3`",
              "correct": true,
              "feedback": "Bonne réponse : `suivant(1)` vaut 2, et `suivant(2)` vaut 3.\n"
            },
            {
              "text": "`2 2`",
              "correct": false,
              "feedback": "Erreur : le second appel reçoit 2 en argument, il renvoie 3.\n"
            },
            {
              "text": "`1 2`",
              "correct": false,
              "feedback": "Erreur : le premier appel renvoie déjà 2.\n"
            },
            {
              "text": "`3 3`",
              "correct": false,
              "feedback": "Erreur : le premier appel n'ajoute 1 qu'une fois.\n"
            }
          ],
          "explanation": "Chaque appel est indépendant et reçoit ses propres arguments. Quand\nun appel sert d'argument à un autre, on calcule d'abord le plus\nintérieur."
        },
        {
          "statement": "```python\ndef suivant(n):\n    return n + 1\nprint(suivant(4), suivant(suivant(4)))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`5 6`",
              "correct": true,
              "feedback": "Bonne réponse : `suivant(4)` vaut 5, et `suivant(5)` vaut 6.\n"
            },
            {
              "text": "`5 5`",
              "correct": false,
              "feedback": "Erreur : le second appel reçoit 5 en argument, il renvoie 6.\n"
            },
            {
              "text": "`4 5`",
              "correct": false,
              "feedback": "Erreur : le premier appel renvoie déjà 5.\n"
            },
            {
              "text": "`6 6`",
              "correct": false,
              "feedback": "Erreur : le premier appel n'ajoute 1 qu'une fois.\n"
            }
          ],
          "explanation": "Chaque appel est indépendant et reçoit ses propres arguments. Quand\nun appel sert d'argument à un autre, on calcule d'abord le plus\nintérieur."
        },
        {
          "statement": "```python\ndef suivant(n):\n    return n + 1\nprint(suivant(10), suivant(suivant(10)))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`11 12`",
              "correct": true,
              "feedback": "Bonne réponse : `suivant(10)` vaut 11, et `suivant(11)` vaut 12.\n"
            },
            {
              "text": "`11 11`",
              "correct": false,
              "feedback": "Erreur : le second appel reçoit 11 en argument, il renvoie 12.\n"
            },
            {
              "text": "`10 11`",
              "correct": false,
              "feedback": "Erreur : le premier appel renvoie déjà 11.\n"
            },
            {
              "text": "`12 12`",
              "correct": false,
              "feedback": "Erreur : le premier appel n'ajoute 1 qu'une fois.\n"
            }
          ],
          "explanation": "Chaque appel est indépendant et reçoit ses propres arguments. Quand\nun appel sert d'argument à un autre, on calcule d'abord le plus\nintérieur."
        }
      ]
    },
    {
      "id": "q15",
      "difficulty": 3,
      "skills": [
        "parametres",
        "portee",
        "return"
      ],
      "title": "Le paramètre n'est pas la variable extérieure",
      "statement": "```python\ndef augmenter(n):\n    n = n + 5\n    return n\nvaleur = 10\naugmenter(valeur)\nprint(valeur)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`10`",
          "correct": true,
          "feedback": "Bonne réponse : la fonction travaille sur son paramètre `n`, une\ncopie de la valeur. `valeur` n'est pas modifiée, et le résultat\nrenvoyé, 15, n'est pas conservé.\n"
        },
        {
          "text": "`15`",
          "correct": false,
          "feedback": "Erreur : 15 est renvoyé mais jamais rangé. Il faudrait écrire\n`valeur = augmenter(valeur)`.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : rien ne ramène `valeur` à 5, elle reste à 10.\n"
        },
        {
          "text": "`None`",
          "correct": false,
          "feedback": "Erreur : `valeur` a bien une valeur, 10, inchangée par l'appel.\n"
        }
      ],
      "explanation": "Un paramètre reçoit une copie de l'argument. Modifier le paramètre ne\nchange pas la variable de l'appelant : pour garder un résultat, on\naffecte la valeur renvoyée.",
      "variants": [
        {
          "statement": "```python\ndef augmenter(n):\n    n = n + 5\n    return n\nvaleur = 10\naugmenter(valeur)\nprint(valeur)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`10`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction travaille sur son paramètre `n`, une\ncopie de la valeur. `valeur` n'est pas modifiée, et le résultat\nrenvoyé, 15, n'est pas conservé.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : 15 est renvoyé mais jamais rangé. Il faudrait écrire\n`valeur = augmenter(valeur)`.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : rien ne ramène `valeur` à 5, elle reste à 10.\n"
            },
            {
              "text": "`None`",
              "correct": false,
              "feedback": "Erreur : `valeur` a bien une valeur, 10, inchangée par l'appel.\n"
            }
          ],
          "explanation": "Un paramètre reçoit une copie de l'argument. Modifier le paramètre ne\nchange pas la variable de l'appelant : pour garder un résultat, on\naffecte la valeur renvoyée."
        },
        {
          "statement": "```python\ndef augmenter(n):\n    n = n + 3\n    return n\nvaleur = 8\naugmenter(valeur)\nprint(valeur)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`8`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction travaille sur son paramètre `n`, une\ncopie de la valeur. `valeur` n'est pas modifiée, et le résultat\nrenvoyé, 11, n'est pas conservé.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : 11 est renvoyé mais jamais rangé. Il faudrait écrire\n`valeur = augmenter(valeur)`.\n"
            },
            {
              "text": "`3`",
              "correct": false,
              "feedback": "Erreur : rien ne ramène `valeur` à 3, elle reste à 8.\n"
            },
            {
              "text": "`None`",
              "correct": false,
              "feedback": "Erreur : `valeur` a bien une valeur, 8, inchangée par l'appel.\n"
            }
          ],
          "explanation": "Un paramètre reçoit une copie de l'argument. Modifier le paramètre ne\nchange pas la variable de l'appelant : pour garder un résultat, on\naffecte la valeur renvoyée."
        },
        {
          "statement": "```python\ndef augmenter(n):\n    n = n + 7\n    return n\nvaleur = 20\naugmenter(valeur)\nprint(valeur)\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`20`",
              "correct": true,
              "feedback": "Bonne réponse : la fonction travaille sur son paramètre `n`, une\ncopie de la valeur. `valeur` n'est pas modifiée, et le résultat\nrenvoyé, 27, n'est pas conservé.\n"
            },
            {
              "text": "`27`",
              "correct": false,
              "feedback": "Erreur : 27 est renvoyé mais jamais rangé. Il faudrait écrire\n`valeur = augmenter(valeur)`.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : rien ne ramène `valeur` à 7, elle reste à 20.\n"
            },
            {
              "text": "`None`",
              "correct": false,
              "feedback": "Erreur : `valeur` a bien une valeur, 20, inchangée par l'appel.\n"
            }
          ],
          "explanation": "Un paramètre reçoit une copie de l'argument. Modifier le paramètre ne\nchange pas la variable de l'appelant : pour garder un résultat, on\naffecte la valeur renvoyée."
        }
      ]
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "fonction",
        "completer-code"
      ],
      "title": "Écrire la bonne fonction",
      "statement": "Quelle fonction renvoie le périmètre d'un rectangle de largeur `l`\net de hauteur `h` ?",
      "options": [
        {
          "text": "`def perimetre(l, h): return 2 * (l + h)`",
          "correct": true,
          "feedback": "Bonne réponse : le périmètre est le double de la somme des deux\ndimensions, et la valeur est renvoyée avec `return`.\n"
        },
        {
          "text": "`def perimetre(l, h): return l * h`",
          "correct": false,
          "feedback": "Erreur : `l * h` est l'aire, pas le périmètre.\n"
        },
        {
          "text": "`def perimetre(l, h): print(2 * (l + h))`",
          "correct": false,
          "feedback": "Erreur : le calcul est juste, mais il est affiché et non\nrenvoyé. La fonction renverrait `None`.\n"
        },
        {
          "text": "`def perimetre(l, h): return 2 * l + h`",
          "correct": false,
          "feedback": "Erreur : sans parenthèses, seule la largeur est doublée.\n"
        }
      ],
      "explanation": "Une fonction qui calcule doit renvoyer son résultat avec `return`,\npour que l'appelant puisse s'en servir. Et les parenthèses restent\nindispensables dans la formule."
    },
    {
      "id": "q17",
      "difficulty": 3,
      "skills": [
        "fonction",
        "while",
        "return"
      ],
      "title": "Une boucle dans une fonction",
      "statement": "```python\ndef premier_multiple(n, seuil):\n    k = 1\n    while n * k <= seuil:\n        k = k + 1\n    return n * k\nprint(premier_multiple(7, 30))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`35`",
          "correct": true,
          "feedback": "Bonne réponse : `k` augmente tant que `7 * k` reste inférieur ou\négal à 30, jusqu'à 5. La fonction renvoie 35, le premier\nmultiple de 7 au-delà de 30.\n"
        },
        {
          "text": "`28`",
          "correct": false,
          "feedback": "Erreur : 28 est encore inférieur ou égal à 30, la boucle\ncontinue et `k` passe à 5.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : 5 est la valeur finale de `k`, mais la fonction renvoie\n`n * k`.\n"
        },
        {
          "text": "`4`",
          "correct": false,
          "feedback": "Erreur : ni `k` ni le résultat ne valent 4 à la fin.\n"
        }
      ],
      "explanation": "Une fonction peut contenir une boucle, et renvoyer une valeur\ncalculée après elle. On suit `k` tour par tour, puis on applique le\n`return`.",
      "variants": [
        {
          "statement": "```python\ndef premier_multiple(n, seuil):\n    k = 1\n    while n * k <= seuil:\n        k = k + 1\n    return n * k\nprint(premier_multiple(7, 30))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`35`",
              "correct": true,
              "feedback": "Bonne réponse : `k` augmente tant que `7 * k` reste inférieur ou\négal à 30, jusqu'à 5. La fonction renvoie 35, le premier\nmultiple de 7 au-delà de 30.\n"
            },
            {
              "text": "`28`",
              "correct": false,
              "feedback": "Erreur : 28 est encore inférieur ou égal à 30, la boucle\ncontinue et `k` passe à 5.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : 5 est la valeur finale de `k`, mais la fonction renvoie\n`n * k`.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : ni `k` ni le résultat ne valent 4 à la fin.\n"
            }
          ],
          "explanation": "Une fonction peut contenir une boucle, et renvoyer une valeur\ncalculée après elle. On suit `k` tour par tour, puis on applique le\n`return`."
        },
        {
          "statement": "```python\ndef premier_multiple(n, seuil):\n    k = 1\n    while n * k <= seuil:\n        k = k + 1\n    return n * k\nprint(premier_multiple(6, 40))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`42`",
              "correct": true,
              "feedback": "Bonne réponse : `k` augmente tant que `6 * k` reste inférieur ou\négal à 40, jusqu'à 7. La fonction renvoie 42, le premier\nmultiple de 6 au-delà de 40.\n"
            },
            {
              "text": "`36`",
              "correct": false,
              "feedback": "Erreur : 36 est encore inférieur ou égal à 40, la boucle\ncontinue et `k` passe à 7.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : 7 est la valeur finale de `k`, mais la fonction renvoie\n`n * k`.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : ni `k` ni le résultat ne valent 6 à la fin.\n"
            }
          ],
          "explanation": "Une fonction peut contenir une boucle, et renvoyer une valeur\ncalculée après elle. On suit `k` tour par tour, puis on applique le\n`return`."
        },
        {
          "statement": "```python\ndef premier_multiple(n, seuil):\n    k = 1\n    while n * k <= seuil:\n        k = k + 1\n    return n * k\nprint(premier_multiple(9, 50))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`54`",
              "correct": true,
              "feedback": "Bonne réponse : `k` augmente tant que `9 * k` reste inférieur ou\négal à 50, jusqu'à 6. La fonction renvoie 54, le premier\nmultiple de 9 au-delà de 50.\n"
            },
            {
              "text": "`45`",
              "correct": false,
              "feedback": "Erreur : 45 est encore inférieur ou égal à 50, la boucle\ncontinue et `k` passe à 6.\n"
            },
            {
              "text": "`6`",
              "correct": false,
              "feedback": "Erreur : 6 est la valeur finale de `k`, mais la fonction renvoie\n`n * k`.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : ni `k` ni le résultat ne valent 5 à la fin.\n"
            }
          ],
          "explanation": "Une fonction peut contenir une boucle, et renvoyer une valeur\ncalculée après elle. On suit `k` tour par tour, puis on applique le\n`return`."
        }
      ]
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "appel",
        "return",
        "print"
      ],
      "title": "Deux affichages",
      "statement": "```python\ndef f(x):\n    return x * 10\nprint(f(2))\nprint(f(2) + f(3))\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "`20` puis `50`",
          "correct": true,
          "feedback": "Bonne réponse : `f(2)` vaut 20, et `f(2) + f(3)` vaut 20 plus\n30.\n"
        },
        {
          "text": "`20` puis `20`",
          "correct": false,
          "feedback": "Erreur : la seconde ligne additionne deux appels, 20 et 30.\n"
        },
        {
          "text": "`20` puis `2030`",
          "correct": false,
          "feedback": "Erreur : les résultats sont des entiers, `+` les additionne.\n"
        },
        {
          "text": "`50` puis `20`",
          "correct": false,
          "feedback": "Erreur : c'est l'ordre inverse des lignes du programme.\n"
        }
      ],
      "explanation": "Chaque appel renvoie une valeur, utilisable dans un calcul. Une\nfonction peut être appelée autant de fois qu'on veut, avec des\narguments différents.",
      "variants": [
        {
          "statement": "```python\ndef f(x):\n    return x * 10\nprint(f(2))\nprint(f(2) + f(3))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`20` puis `50`",
              "correct": true,
              "feedback": "Bonne réponse : `f(2)` vaut 20, et `f(2) + f(3)` vaut 20 plus\n30.\n"
            },
            {
              "text": "`20` puis `20`",
              "correct": false,
              "feedback": "Erreur : la seconde ligne additionne deux appels, 20 et 30.\n"
            },
            {
              "text": "`20` puis `2030`",
              "correct": false,
              "feedback": "Erreur : les résultats sont des entiers, `+` les additionne.\n"
            },
            {
              "text": "`50` puis `20`",
              "correct": false,
              "feedback": "Erreur : c'est l'ordre inverse des lignes du programme.\n"
            }
          ],
          "explanation": "Chaque appel renvoie une valeur, utilisable dans un calcul. Une\nfonction peut être appelée autant de fois qu'on veut, avec des\narguments différents."
        },
        {
          "statement": "```python\ndef f(x):\n    return x * 5\nprint(f(4))\nprint(f(4) + f(3))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`20` puis `35`",
              "correct": true,
              "feedback": "Bonne réponse : `f(4)` vaut 20, et `f(4) + f(3)` vaut 20 plus\n15.\n"
            },
            {
              "text": "`20` puis `20`",
              "correct": false,
              "feedback": "Erreur : la seconde ligne additionne deux appels, 20 et 15.\n"
            },
            {
              "text": "`20` puis `2015`",
              "correct": false,
              "feedback": "Erreur : les résultats sont des entiers, `+` les additionne.\n"
            },
            {
              "text": "`35` puis `20`",
              "correct": false,
              "feedback": "Erreur : c'est l'ordre inverse des lignes du programme.\n"
            }
          ],
          "explanation": "Chaque appel renvoie une valeur, utilisable dans un calcul. Une\nfonction peut être appelée autant de fois qu'on veut, avec des\narguments différents."
        },
        {
          "statement": "```python\ndef f(x):\n    return x * 100\nprint(f(1))\nprint(f(1) + f(2))\n```\n\nQu'affiche ce programme ?",
          "options": [
            {
              "text": "`100` puis `300`",
              "correct": true,
              "feedback": "Bonne réponse : `f(1)` vaut 100, et `f(1) + f(2)` vaut 100 plus\n200.\n"
            },
            {
              "text": "`100` puis `100`",
              "correct": false,
              "feedback": "Erreur : la seconde ligne additionne deux appels, 100 et 200.\n"
            },
            {
              "text": "`100` puis `100200`",
              "correct": false,
              "feedback": "Erreur : les résultats sont des entiers, `+` les additionne.\n"
            },
            {
              "text": "`300` puis `100`",
              "correct": false,
              "feedback": "Erreur : c'est l'ordre inverse des lignes du programme.\n"
            }
          ],
          "explanation": "Chaque appel renvoie une valeur, utilisable dans un calcul. Une\nfonction peut être appelée autant de fois qu'on veut, avec des\narguments différents."
        }
      ]
    },
    {
      "id": "q19",
      "difficulty": 3,
      "skills": [
        "fonction",
        "booleens",
        "condition",
        "for"
      ],
      "title": "Une fonction dans un test",
      "statement": "```python\ndef est_pair(n):\n    return n % 2 == 0\n\nfor k in range(1, 7):\n    if est_pair(k):\n        print(k)\n```\n\nQu'affiche ce programme ?",
      "options": [
        {
          "text": "2, 4 et 6",
          "correct": true,
          "feedback": "Bonne réponse : la fonction renvoie `True` pour les nombres\npairs, et seuls ceux-là sont affichés.\n"
        },
        {
          "text": "1, 3 et 5",
          "correct": false,
          "feedback": "Erreur : `n % 2 == 0` est vrai pour les pairs.\n"
        },
        {
          "text": "`True`, `True` et `True`",
          "correct": false,
          "feedback": "Erreur : le programme affiche `k`, pas le résultat de la\nfonction.\n"
        },
        {
          "text": "2 et 4",
          "correct": false,
          "feedback": "Erreur : `range(1, 7)` va jusqu'à 6, qui est pair.\n"
        }
      ],
      "explanation": "Une fonction qui renvoie un booléen s'utilise directement comme\ncondition dans un `if`. Elle donne un nom parlant au test et évite de\nrépéter la formule."
    },
    {
      "id": "q20",
      "difficulty": 1,
      "skills": [
        "fonction"
      ],
      "title": "À quoi sert une fonction",
      "statement": "Pourquoi définit-on une fonction dans un programme ?",
      "options": [
        {
          "text": "Pour réutiliser un même traitement avec des valeurs différentes",
          "correct": true,
          "feedback": "Bonne réponse : une fonction écrite une fois s'appelle autant de\nfois que nécessaire, avec d'autres arguments. Le programme est\nplus court et plus lisible.\n"
        },
        {
          "text": "Pour rendre l'exécution du programme plus rapide",
          "correct": false,
          "feedback": "Erreur : une fonction ne change pas la vitesse d'exécution. Son\nintérêt est l'organisation du code.\n"
        },
        {
          "text": "Pour se passer de variables dans le programme",
          "correct": false,
          "feedback": "Erreur : les fonctions utilisent des variables, paramètres et\nvariables locales.\n"
        },
        {
          "text": "Pour afficher automatiquement chaque résultat",
          "correct": false,
          "feedback": "Erreur : une fonction n'affiche rien par elle-même. Elle renvoie\nune valeur, que l'appelant affiche s'il le souhaite.\n"
        }
      ],
      "explanation": "Une fonction regroupe un traitement sous un nom. On l'écrit une fois\net on l'appelle partout où l'on en a besoin, ce qui évite les\nrépétitions et facilite les corrections."
    },
    {
      "id": "q21",
      "difficulty": 1,
      "skills": [
        "fonction",
        "return",
        "appel"
      ],
      "title": "Le carré d'un nombre",
      "statement": "Qu'affiche ce programme ?\n```python\ndef carre(x):\n    return x * x\n\nprint(carre(5))\n```",
      "options": [
        {
          "text": "`25`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel `carre(5)` donne la valeur 5 au\nparamètre `x`, et la fonction renvoie 5 × 5 = 25.\n"
        },
        {
          "text": "`10`",
          "correct": false,
          "feedback": "Erreur : `x * x` multiplie `x` par lui-même, ce n'est pas le\ndouble.\n"
        },
        {
          "text": "`x * x`",
          "correct": false,
          "feedback": "Erreur : `return` renvoie le résultat du calcul, pas son\nécriture.\n"
        },
        {
          "text": "Rien, la fonction ne contenant pas de `print`",
          "correct": false,
          "feedback": "Erreur : le `print` entoure l'appel et affiche la valeur\nrenvoyée.\n"
        }
      ],
      "explanation": "Appeler une fonction, c'est remplacer son paramètre par l'argument\net récupérer ce que `return` renvoie.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef carre(x):\n    return x * x\n\nprint(carre(5))\n```",
          "options": [
            {
              "text": "`25`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `carre(5)` donne la valeur 5 au\nparamètre `x`, et la fonction renvoie 5 × 5 = 25.\n"
            },
            {
              "text": "`10`",
              "correct": false,
              "feedback": "Erreur : `x * x` multiplie `x` par lui-même, ce n'est pas le\ndouble.\n"
            },
            {
              "text": "`x * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas son\nécriture.\n"
            },
            {
              "text": "Rien, la fonction ne contenant pas de `print`",
              "correct": false,
              "feedback": "Erreur : le `print` entoure l'appel et affiche la valeur\nrenvoyée.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est remplacer son paramètre par l'argument\net récupérer ce que `return` renvoie."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef carre(x):\n    return x * x\n\nprint(carre(7))\n```",
          "options": [
            {
              "text": "`49`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `carre(7)` donne la valeur 7 au\nparamètre `x`, et la fonction renvoie 7 × 7 = 49.\n"
            },
            {
              "text": "`14`",
              "correct": false,
              "feedback": "Erreur : `x * x` multiplie `x` par lui-même, ce n'est pas le\ndouble.\n"
            },
            {
              "text": "`x * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas son\nécriture.\n"
            },
            {
              "text": "Rien, la fonction ne contenant pas de `print`",
              "correct": false,
              "feedback": "Erreur : le `print` entoure l'appel et affiche la valeur\nrenvoyée.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est remplacer son paramètre par l'argument\net récupérer ce que `return` renvoie."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef carre(x):\n    return x * x\n\nprint(carre(12))\n```",
          "options": [
            {
              "text": "`144`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel `carre(12)` donne la valeur 12 au\nparamètre `x`, et la fonction renvoie 12 × 12 = 144.\n"
            },
            {
              "text": "`24`",
              "correct": false,
              "feedback": "Erreur : `x * x` multiplie `x` par lui-même, ce n'est pas le\ndouble.\n"
            },
            {
              "text": "`x * x`",
              "correct": false,
              "feedback": "Erreur : `return` renvoie le résultat du calcul, pas son\nécriture.\n"
            },
            {
              "text": "Rien, la fonction ne contenant pas de `print`",
              "correct": false,
              "feedback": "Erreur : le `print` entoure l'appel et affiche la valeur\nrenvoyée.\n"
            }
          ],
          "explanation": "Appeler une fonction, c'est remplacer son paramètre par l'argument\net récupérer ce que `return` renvoie."
        }
      ]
    },
    {
      "id": "q22",
      "difficulty": 1,
      "skills": [
        "fonction",
        "appel",
        "sans-parametre"
      ],
      "title": "Une fonction appelée plusieurs fois",
      "statement": "Combien de fois ce programme affiche-t-il `Bonjour` ?\n```python\ndef saluer():\n    print(\"Bonjour\")\n\nsaluer()\nsaluer()\n```",
      "options": [
        {
          "text": "deux fois",
          "correct": true,
          "feedback": "Bonne réponse : la définition n'affiche rien, mais chaque appel\n`saluer()` exécute le corps de la fonction.\n"
        },
        {
          "text": "Une seule fois, la fonction n'étant définie qu'une fois",
          "correct": false,
          "feedback": "Erreur : définir une fonction ne l'exécute pas ; ce sont les\nappels qui comptent, et il y en a deux.\n"
        },
        {
          "text": "3 fois, la définition comptant pour un affichage",
          "correct": false,
          "feedback": "Erreur : la ligne `def` ne provoque aucun affichage.\n"
        },
        {
          "text": "Aucune fois, la fonction ne renvoyant rien",
          "correct": false,
          "feedback": "Erreur : une fonction sans `return` peut tout de même afficher\navec `print`.\n"
        }
      ],
      "explanation": "Une fonction s'écrit une fois et s'appelle autant de fois que\nnécessaire. Chaque appel exécute son corps.",
      "variants": [
        {
          "statement": "Combien de fois ce programme affiche-t-il `Bonjour` ?\n```python\ndef saluer():\n    print(\"Bonjour\")\n\nsaluer()\nsaluer()\n```",
          "options": [
            {
              "text": "deux fois",
              "correct": true,
              "feedback": "Bonne réponse : la définition n'affiche rien, mais chaque appel\n`saluer()` exécute le corps de la fonction.\n"
            },
            {
              "text": "Une seule fois, la fonction n'étant définie qu'une fois",
              "correct": false,
              "feedback": "Erreur : définir une fonction ne l'exécute pas ; ce sont les\nappels qui comptent, et il y en a deux.\n"
            },
            {
              "text": "3 fois, la définition comptant pour un affichage",
              "correct": false,
              "feedback": "Erreur : la ligne `def` ne provoque aucun affichage.\n"
            },
            {
              "text": "Aucune fois, la fonction ne renvoyant rien",
              "correct": false,
              "feedback": "Erreur : une fonction sans `return` peut tout de même afficher\navec `print`.\n"
            }
          ],
          "explanation": "Une fonction s'écrit une fois et s'appelle autant de fois que\nnécessaire. Chaque appel exécute son corps."
        },
        {
          "statement": "Combien de fois ce programme affiche-t-il `Bonjour` ?\n```python\ndef saluer():\n    print(\"Bonjour\")\n\nsaluer()\nsaluer()\nsaluer()\n```",
          "options": [
            {
              "text": "trois fois",
              "correct": true,
              "feedback": "Bonne réponse : la définition n'affiche rien, mais chaque appel\n`saluer()` exécute le corps de la fonction.\n"
            },
            {
              "text": "Une seule fois, la fonction n'étant définie qu'une fois",
              "correct": false,
              "feedback": "Erreur : définir une fonction ne l'exécute pas ; ce sont les\nappels qui comptent, et il y en a trois.\n"
            },
            {
              "text": "4 fois, la définition comptant pour un affichage",
              "correct": false,
              "feedback": "Erreur : la ligne `def` ne provoque aucun affichage.\n"
            },
            {
              "text": "Aucune fois, la fonction ne renvoyant rien",
              "correct": false,
              "feedback": "Erreur : une fonction sans `return` peut tout de même afficher\navec `print`.\n"
            }
          ],
          "explanation": "Une fonction s'écrit une fois et s'appelle autant de fois que\nnécessaire. Chaque appel exécute son corps."
        },
        {
          "statement": "Combien de fois ce programme affiche-t-il `Bonjour` ?\n```python\ndef saluer():\n    print(\"Bonjour\")\n\nsaluer()\nsaluer()\nsaluer()\nsaluer()\n```",
          "options": [
            {
              "text": "quatre fois",
              "correct": true,
              "feedback": "Bonne réponse : la définition n'affiche rien, mais chaque appel\n`saluer()` exécute le corps de la fonction.\n"
            },
            {
              "text": "Une seule fois, la fonction n'étant définie qu'une fois",
              "correct": false,
              "feedback": "Erreur : définir une fonction ne l'exécute pas ; ce sont les\nappels qui comptent, et il y en a quatre.\n"
            },
            {
              "text": "5 fois, la définition comptant pour un affichage",
              "correct": false,
              "feedback": "Erreur : la ligne `def` ne provoque aucun affichage.\n"
            },
            {
              "text": "Aucune fois, la fonction ne renvoyant rien",
              "correct": false,
              "feedback": "Erreur : une fonction sans `return` peut tout de même afficher\navec `print`.\n"
            }
          ],
          "explanation": "Une fonction s'écrit une fois et s'appelle autant de fois que\nnécessaire. Chaque appel exécute son corps."
        }
      ]
    },
    {
      "id": "q23",
      "difficulty": 1,
      "skills": [
        "fonction",
        "return",
        "variable"
      ],
      "title": "Un résultat rangé dans une variable",
      "statement": "Qu'affiche ce programme ?\n```python\ndef aire(largeur, hauteur):\n    return largeur * hauteur\n\nr = aire(3, 4)\nprint(r)\n```",
      "options": [
        {
          "text": "`12`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel renvoie 3 × 4 = 12, rangé dans `r`\npuis affiché.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : la fonction multiplie ses deux paramètres.\n"
        },
        {
          "text": "`aire(3, 4)`",
          "correct": false,
          "feedback": "Erreur : `r` contient le résultat de l'appel, pas son écriture.\n"
        },
        {
          "text": "Rien, `r` ne pouvant recevoir une fonction",
          "correct": false,
          "feedback": "Erreur : `r` reçoit la valeur renvoyée par la fonction, un\nnombre.\n"
        }
      ],
      "explanation": "La valeur renvoyée par `return` peut être rangée dans une variable\npour servir plus tard.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef aire(largeur, hauteur):\n    return largeur * hauteur\n\nr = aire(3, 4)\nprint(r)\n```",
          "options": [
            {
              "text": "`12`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel renvoie 3 × 4 = 12, rangé dans `r`\npuis affiché.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie ses deux paramètres.\n"
            },
            {
              "text": "`aire(3, 4)`",
              "correct": false,
              "feedback": "Erreur : `r` contient le résultat de l'appel, pas son écriture.\n"
            },
            {
              "text": "Rien, `r` ne pouvant recevoir une fonction",
              "correct": false,
              "feedback": "Erreur : `r` reçoit la valeur renvoyée par la fonction, un\nnombre.\n"
            }
          ],
          "explanation": "La valeur renvoyée par `return` peut être rangée dans une variable\npour servir plus tard."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef aire(largeur, hauteur):\n    return largeur * hauteur\n\nr = aire(5, 6)\nprint(r)\n```",
          "options": [
            {
              "text": "`30`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel renvoie 5 × 6 = 30, rangé dans `r`\npuis affiché.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie ses deux paramètres.\n"
            },
            {
              "text": "`aire(5, 6)`",
              "correct": false,
              "feedback": "Erreur : `r` contient le résultat de l'appel, pas son écriture.\n"
            },
            {
              "text": "Rien, `r` ne pouvant recevoir une fonction",
              "correct": false,
              "feedback": "Erreur : `r` reçoit la valeur renvoyée par la fonction, un\nnombre.\n"
            }
          ],
          "explanation": "La valeur renvoyée par `return` peut être rangée dans une variable\npour servir plus tard."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef aire(largeur, hauteur):\n    return largeur * hauteur\n\nr = aire(2, 9)\nprint(r)\n```",
          "options": [
            {
              "text": "`18`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel renvoie 2 × 9 = 18, rangé dans `r`\npuis affiché.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : la fonction multiplie ses deux paramètres.\n"
            },
            {
              "text": "`aire(2, 9)`",
              "correct": false,
              "feedback": "Erreur : `r` contient le résultat de l'appel, pas son écriture.\n"
            },
            {
              "text": "Rien, `r` ne pouvant recevoir une fonction",
              "correct": false,
              "feedback": "Erreur : `r` reçoit la valeur renvoyée par la fonction, un\nnombre.\n"
            }
          ],
          "explanation": "La valeur renvoyée par `return` peut être rangée dans une variable\npour servir plus tard."
        }
      ]
    },
    {
      "id": "q24",
      "difficulty": 3,
      "skills": [
        "fonction",
        "print",
        "none"
      ],
      "title": "Une fonction qui affiche au lieu de renvoyer",
      "statement": "Qu'affiche ce programme ?\n```python\ndef montrer(x):\n    print(x)\n\nr = montrer(3)\nprint(r)\n```",
      "options": [
        {
          "text": "`3` puis `None`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel affiche 3, mais la fonction ne renvoie\nrien ; `r` reçoit donc `None`, la valeur « rien », que le second\n`print` affiche.\n"
        },
        {
          "text": "`3` puis `3`",
          "correct": false,
          "feedback": "Erreur : sans `return`, la fonction ne transmet pas 3 à\nl'appelant.\n"
        },
        {
          "text": "`3` seulement",
          "correct": false,
          "feedback": "Erreur : le second `print` affiche quand même quelque chose, la\nvaleur `None`.\n"
        },
        {
          "text": "Une erreur, `r` ne recevant aucune valeur",
          "correct": false,
          "feedback": "Erreur : Python ne signale rien ; il range `None` dans `r`.\n"
        }
      ],
      "explanation": "`print` affiche, `return` renvoie. Une fonction sans `return`\nrenvoie `None`, ce qui trahit souvent une confusion entre les deux.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef montrer(x):\n    print(x)\n\nr = montrer(3)\nprint(r)\n```",
          "options": [
            {
              "text": "`3` puis `None`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel affiche 3, mais la fonction ne renvoie\nrien ; `r` reçoit donc `None`, la valeur « rien », que le second\n`print` affiche.\n"
            },
            {
              "text": "`3` puis `3`",
              "correct": false,
              "feedback": "Erreur : sans `return`, la fonction ne transmet pas 3 à\nl'appelant.\n"
            },
            {
              "text": "`3` seulement",
              "correct": false,
              "feedback": "Erreur : le second `print` affiche quand même quelque chose, la\nvaleur `None`.\n"
            },
            {
              "text": "Une erreur, `r` ne recevant aucune valeur",
              "correct": false,
              "feedback": "Erreur : Python ne signale rien ; il range `None` dans `r`.\n"
            }
          ],
          "explanation": "`print` affiche, `return` renvoie. Une fonction sans `return`\nrenvoie `None`, ce qui trahit souvent une confusion entre les deux."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef montrer(x):\n    print(x)\n\nr = montrer(10)\nprint(r)\n```",
          "options": [
            {
              "text": "`10` puis `None`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel affiche 10, mais la fonction ne renvoie\nrien ; `r` reçoit donc `None`, la valeur « rien », que le second\n`print` affiche.\n"
            },
            {
              "text": "`10` puis `10`",
              "correct": false,
              "feedback": "Erreur : sans `return`, la fonction ne transmet pas 10 à\nl'appelant.\n"
            },
            {
              "text": "`10` seulement",
              "correct": false,
              "feedback": "Erreur : le second `print` affiche quand même quelque chose, la\nvaleur `None`.\n"
            },
            {
              "text": "Une erreur, `r` ne recevant aucune valeur",
              "correct": false,
              "feedback": "Erreur : Python ne signale rien ; il range `None` dans `r`.\n"
            }
          ],
          "explanation": "`print` affiche, `return` renvoie. Une fonction sans `return`\nrenvoie `None`, ce qui trahit souvent une confusion entre les deux."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef montrer(x):\n    print(x)\n\nr = montrer(7)\nprint(r)\n```",
          "options": [
            {
              "text": "`7` puis `None`",
              "correct": true,
              "feedback": "Bonne réponse : l'appel affiche 7, mais la fonction ne renvoie\nrien ; `r` reçoit donc `None`, la valeur « rien », que le second\n`print` affiche.\n"
            },
            {
              "text": "`7` puis `7`",
              "correct": false,
              "feedback": "Erreur : sans `return`, la fonction ne transmet pas 7 à\nl'appelant.\n"
            },
            {
              "text": "`7` seulement",
              "correct": false,
              "feedback": "Erreur : le second `print` affiche quand même quelque chose, la\nvaleur `None`.\n"
            },
            {
              "text": "Une erreur, `r` ne recevant aucune valeur",
              "correct": false,
              "feedback": "Erreur : Python ne signale rien ; il range `None` dans `r`.\n"
            }
          ],
          "explanation": "`print` affiche, `return` renvoie. Une fonction sans `return`\nrenvoie `None`, ce qui trahit souvent une confusion entre les deux."
        }
      ]
    },
    {
      "id": "q25",
      "difficulty": 2,
      "skills": [
        "fonction",
        "argument",
        "expression"
      ],
      "title": "Un calcul passé en argument",
      "statement": "Qu'affiche ce programme ?\n```python\ndef double(x):\n    return 2 * x\n\nprint(double(2 + 3))\n```",
      "options": [
        {
          "text": "`10`",
          "correct": true,
          "feedback": "Bonne réponse : l'argument `2 + 3` est calculé avant l'appel,\npuis la fonction double 5.\n"
        },
        {
          "text": "`7`",
          "correct": false,
          "feedback": "Erreur : c'est la somme entière qui est doublée, pas seulement\n2.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : la fonction double la valeur reçue.\n"
        },
        {
          "text": "Une erreur, un argument devant être une simple valeur",
          "correct": false,
          "feedback": "Erreur : tout calcul peut servir d'argument, il est évalué\nd'abord.\n"
        }
      ],
      "explanation": "Les arguments sont évalués avant l'appel : la fonction reçoit le\nrésultat du calcul, pas le calcul.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef double(x):\n    return 2 * x\n\nprint(double(2 + 3))\n```",
          "options": [
            {
              "text": "`10`",
              "correct": true,
              "feedback": "Bonne réponse : l'argument `2 + 3` est calculé avant l'appel,\npuis la fonction double 5.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : c'est la somme entière qui est doublée, pas seulement\n2.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : la fonction double la valeur reçue.\n"
            },
            {
              "text": "Une erreur, un argument devant être une simple valeur",
              "correct": false,
              "feedback": "Erreur : tout calcul peut servir d'argument, il est évalué\nd'abord.\n"
            }
          ],
          "explanation": "Les arguments sont évalués avant l'appel : la fonction reçoit le\nrésultat du calcul, pas le calcul."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef double(x):\n    return 2 * x\n\nprint(double(4 + 5))\n```",
          "options": [
            {
              "text": "`18`",
              "correct": true,
              "feedback": "Bonne réponse : l'argument `4 + 5` est calculé avant l'appel,\npuis la fonction double 9.\n"
            },
            {
              "text": "`13`",
              "correct": false,
              "feedback": "Erreur : c'est la somme entière qui est doublée, pas seulement\n4.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : la fonction double la valeur reçue.\n"
            },
            {
              "text": "Une erreur, un argument devant être une simple valeur",
              "correct": false,
              "feedback": "Erreur : tout calcul peut servir d'argument, il est évalué\nd'abord.\n"
            }
          ],
          "explanation": "Les arguments sont évalués avant l'appel : la fonction reçoit le\nrésultat du calcul, pas le calcul."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef double(x):\n    return 2 * x\n\nprint(double(1 + 6))\n```",
          "options": [
            {
              "text": "`14`",
              "correct": true,
              "feedback": "Bonne réponse : l'argument `1 + 6` est calculé avant l'appel,\npuis la fonction double 7.\n"
            },
            {
              "text": "`8`",
              "correct": false,
              "feedback": "Erreur : c'est la somme entière qui est doublée, pas seulement\n1.\n"
            },
            {
              "text": "`7`",
              "correct": false,
              "feedback": "Erreur : la fonction double la valeur reçue.\n"
            },
            {
              "text": "Une erreur, un argument devant être une simple valeur",
              "correct": false,
              "feedback": "Erreur : tout calcul peut servir d'argument, il est évalué\nd'abord.\n"
            }
          ],
          "explanation": "Les arguments sont évalués avant l'appel : la fonction reçoit le\nrésultat du calcul, pas le calcul."
        }
      ]
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "fonction",
        "definition",
        "ordre"
      ],
      "title": "Un appel avant la définition",
      "statement": "Que produit ce programme ?\n```python\nprint(triple(4))\n\ndef triple(x):\n    return 3 * x\n```",
      "options": [
        {
          "text": "Une erreur, `triple` n'étant pas encore définie",
          "correct": true,
          "feedback": "Bonne réponse : Python lit le programme de haut en bas. À la\npremière ligne, aucune fonction `triple` n'a été définie.\n"
        },
        {
          "text": "`12`, la définition étant lue avant l'exécution",
          "correct": false,
          "feedback": "Erreur : ce serait le résultat si la définition précédait\nl'appel.\n"
        },
        {
          "text": "`4`, l'argument étant affiché faute de fonction",
          "correct": false,
          "feedback": "Erreur : le programme s'arrête avant d'afficher quoi que ce\nsoit.\n"
        },
        {
          "text": "Rien, la définition annulant l'appel précédent",
          "correct": false,
          "feedback": "Erreur : l'appel est exécuté en premier et échoue, la suite\nn'est jamais atteinte.\n"
        }
      ],
      "explanation": "Une fonction doit être définie avant d'être appelée. Les\ndéfinitions se placent en tête du programme."
    },
    {
      "id": "q27",
      "difficulty": 3,
      "skills": [
        "fonction",
        "condition",
        "return"
      ],
      "title": "Deux return sous condition",
      "statement": "Qu'affiche ce programme ?\n```python\ndef tarif(age):\n    if age < 18:\n        return 5\n    return 8\n\nprint(tarif(18))\n```",
      "options": [
        {
          "text": "`8`",
          "correct": true,
          "feedback": "Bonne réponse : si `age < 18`, le premier `return` termine la\nfonction avec 5 ; sinon le second renvoie 8. Avec 18, on\nobtient 8.\n"
        },
        {
          "text": "`5`",
          "correct": false,
          "feedback": "Erreur : relis la condition `age < 18` avec `age` égal à 18.\n"
        },
        {
          "text": "`5` puis `8`",
          "correct": false,
          "feedback": "Erreur : le premier `return` exécuté arrête la fonction, un seul\nrésultat est renvoyé.\n"
        },
        {
          "text": "Une erreur, une fonction ne pouvant contenir deux `return`",
          "correct": false,
          "feedback": "Erreur : plusieurs `return` sont permis, un seul est atteint à\nchaque appel.\n"
        }
      ],
      "explanation": "Un `return` dans un `if` renvoie et sort aussitôt. Le `return` qui\nsuit n'est atteint que si la condition est fausse.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef tarif(age):\n    if age < 18:\n        return 5\n    return 8\n\nprint(tarif(18))\n```",
          "options": [
            {
              "text": "`8`",
              "correct": true,
              "feedback": "Bonne réponse : si `age < 18`, le premier `return` termine la\nfonction avec 5 ; sinon le second renvoie 8. Avec 18, on\nobtient 8.\n"
            },
            {
              "text": "`5`",
              "correct": false,
              "feedback": "Erreur : relis la condition `age < 18` avec `age` égal à 18.\n"
            },
            {
              "text": "`5` puis `8`",
              "correct": false,
              "feedback": "Erreur : le premier `return` exécuté arrête la fonction, un seul\nrésultat est renvoyé.\n"
            },
            {
              "text": "Une erreur, une fonction ne pouvant contenir deux `return`",
              "correct": false,
              "feedback": "Erreur : plusieurs `return` sont permis, un seul est atteint à\nchaque appel.\n"
            }
          ],
          "explanation": "Un `return` dans un `if` renvoie et sort aussitôt. Le `return` qui\nsuit n'est atteint que si la condition est fausse."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef tarif(age):\n    if age < 18:\n        return 6\n    return 9\n\nprint(tarif(17))\n```",
          "options": [
            {
              "text": "`6`",
              "correct": true,
              "feedback": "Bonne réponse : si `age < 18`, le premier `return` termine la\nfonction avec 6 ; sinon le second renvoie 9. Avec 17, on\nobtient 6.\n"
            },
            {
              "text": "`9`",
              "correct": false,
              "feedback": "Erreur : relis la condition `age < 18` avec `age` égal à 17.\n"
            },
            {
              "text": "`6` puis `9`",
              "correct": false,
              "feedback": "Erreur : le premier `return` exécuté arrête la fonction, un seul\nrésultat est renvoyé.\n"
            },
            {
              "text": "Une erreur, une fonction ne pouvant contenir deux `return`",
              "correct": false,
              "feedback": "Erreur : plusieurs `return` sont permis, un seul est atteint à\nchaque appel.\n"
            }
          ],
          "explanation": "Un `return` dans un `if` renvoie et sort aussitôt. Le `return` qui\nsuit n'est atteint que si la condition est fausse."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef tarif(age):\n    if age < 18:\n        return 4\n    return 7\n\nprint(tarif(65))\n```",
          "options": [
            {
              "text": "`7`",
              "correct": true,
              "feedback": "Bonne réponse : si `age < 18`, le premier `return` termine la\nfonction avec 4 ; sinon le second renvoie 7. Avec 65, on\nobtient 7.\n"
            },
            {
              "text": "`4`",
              "correct": false,
              "feedback": "Erreur : relis la condition `age < 18` avec `age` égal à 65.\n"
            },
            {
              "text": "`4` puis `7`",
              "correct": false,
              "feedback": "Erreur : le premier `return` exécuté arrête la fonction, un seul\nrésultat est renvoyé.\n"
            },
            {
              "text": "Une erreur, une fonction ne pouvant contenir deux `return`",
              "correct": false,
              "feedback": "Erreur : plusieurs `return` sont permis, un seul est atteint à\nchaque appel.\n"
            }
          ],
          "explanation": "Un `return` dans un `if` renvoie et sort aussitôt. Le `return` qui\nsuit n'est atteint que si la condition est fausse."
        }
      ]
    },
    {
      "id": "q28",
      "difficulty": 2,
      "skills": [
        "fonction",
        "deux-parametres",
        "calcul"
      ],
      "title": "Le périmètre d'un rectangle",
      "statement": "Qu'affiche ce programme ?\n```python\ndef perimetre(l, L):\n    return 2 * (l + L)\n\nprint(perimetre(3, 5))\n```",
      "options": [
        {
          "text": "`16`",
          "correct": true,
          "feedback": "Bonne réponse : `l` vaut 3 et `L` vaut 5, et\n2 × (3 + 5) = 16.\n"
        },
        {
          "text": "`11`",
          "correct": false,
          "feedback": "Erreur : les parenthèses font porter le doublement sur la somme\nentière.\n"
        },
        {
          "text": "`15`",
          "correct": false,
          "feedback": "Erreur : le produit serait l'aire, la fonction calcule le\npérimètre.\n"
        },
        {
          "text": "Une erreur, `l` et `L` étant le même nom",
          "correct": false,
          "feedback": "Erreur : Python distingue majuscules et minuscules, `l` et `L`\nsont deux paramètres différents.\n"
        }
      ],
      "explanation": "Les arguments sont distribués aux paramètres dans l'ordre, puis le\ncorps de la fonction calcule avec ces valeurs.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef perimetre(l, L):\n    return 2 * (l + L)\n\nprint(perimetre(3, 5))\n```",
          "options": [
            {
              "text": "`16`",
              "correct": true,
              "feedback": "Bonne réponse : `l` vaut 3 et `L` vaut 5, et\n2 × (3 + 5) = 16.\n"
            },
            {
              "text": "`11`",
              "correct": false,
              "feedback": "Erreur : les parenthèses font porter le doublement sur la somme\nentière.\n"
            },
            {
              "text": "`15`",
              "correct": false,
              "feedback": "Erreur : le produit serait l'aire, la fonction calcule le\npérimètre.\n"
            },
            {
              "text": "Une erreur, `l` et `L` étant le même nom",
              "correct": false,
              "feedback": "Erreur : Python distingue majuscules et minuscules, `l` et `L`\nsont deux paramètres différents.\n"
            }
          ],
          "explanation": "Les arguments sont distribués aux paramètres dans l'ordre, puis le\ncorps de la fonction calcule avec ces valeurs."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef perimetre(l, L):\n    return 2 * (l + L)\n\nprint(perimetre(4, 10))\n```",
          "options": [
            {
              "text": "`28`",
              "correct": true,
              "feedback": "Bonne réponse : `l` vaut 4 et `L` vaut 10, et\n2 × (4 + 10) = 28.\n"
            },
            {
              "text": "`18`",
              "correct": false,
              "feedback": "Erreur : les parenthèses font porter le doublement sur la somme\nentière.\n"
            },
            {
              "text": "`40`",
              "correct": false,
              "feedback": "Erreur : le produit serait l'aire, la fonction calcule le\npérimètre.\n"
            },
            {
              "text": "Une erreur, `l` et `L` étant le même nom",
              "correct": false,
              "feedback": "Erreur : Python distingue majuscules et minuscules, `l` et `L`\nsont deux paramètres différents.\n"
            }
          ],
          "explanation": "Les arguments sont distribués aux paramètres dans l'ordre, puis le\ncorps de la fonction calcule avec ces valeurs."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\ndef perimetre(l, L):\n    return 2 * (l + L)\n\nprint(perimetre(7, 2))\n```",
          "options": [
            {
              "text": "`18`",
              "correct": true,
              "feedback": "Bonne réponse : `l` vaut 7 et `L` vaut 2, et\n2 × (7 + 2) = 18.\n"
            },
            {
              "text": "`16`",
              "correct": false,
              "feedback": "Erreur : les parenthèses font porter le doublement sur la somme\nentière.\n"
            },
            {
              "text": "`14`",
              "correct": false,
              "feedback": "Erreur : le produit serait l'aire, la fonction calcule le\npérimètre.\n"
            },
            {
              "text": "Une erreur, `l` et `L` étant le même nom",
              "correct": false,
              "feedback": "Erreur : Python distingue majuscules et minuscules, `l` et `L`\nsont deux paramètres différents.\n"
            }
          ],
          "explanation": "Les arguments sont distribués aux paramètres dans l'ordre, puis le\ncorps de la fonction calcule avec ces valeurs."
        }
      ]
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "fonction",
        "parametre",
        "variable-exterieure"
      ],
      "title": "Un paramètre qui porte le nom d'une variable",
      "statement": "Qu'affiche ce programme ?\n```python\nx = 5\n\ndef f(x):\n    return x + 1\n\nprint(f(10), x)\n```",
      "options": [
        {
          "text": "`11 5`",
          "correct": true,
          "feedback": "Bonne réponse : dans `f`, `x` est le paramètre et vaut 10,\nd'où 11. En dehors, `x` reste la variable initiale, 5.\n"
        },
        {
          "text": "`11 10`",
          "correct": false,
          "feedback": "Erreur : l'appel ne modifie pas la variable `x` extérieure.\n"
        },
        {
          "text": "`6 5`",
          "correct": false,
          "feedback": "Erreur : dans la fonction, `x` prend la valeur de l'argument,\n10, pas celle de la variable extérieure.\n"
        },
        {
          "text": "Une erreur, le nom `x` étant déjà utilisé",
          "correct": false,
          "feedback": "Erreur : un paramètre peut porter le même nom qu'une variable\nextérieure, les deux restent indépendants.\n"
        }
      ],
      "explanation": "Le paramètre d'une fonction est une variable locale : même nom\nqu'une variable extérieure ou non, il vit séparément.",
      "variants": [
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 5\n\ndef f(x):\n    return x + 1\n\nprint(f(10), x)\n```",
          "options": [
            {
              "text": "`11 5`",
              "correct": true,
              "feedback": "Bonne réponse : dans `f`, `x` est le paramètre et vaut 10,\nd'où 11. En dehors, `x` reste la variable initiale, 5.\n"
            },
            {
              "text": "`11 10`",
              "correct": false,
              "feedback": "Erreur : l'appel ne modifie pas la variable `x` extérieure.\n"
            },
            {
              "text": "`6 5`",
              "correct": false,
              "feedback": "Erreur : dans la fonction, `x` prend la valeur de l'argument,\n10, pas celle de la variable extérieure.\n"
            },
            {
              "text": "Une erreur, le nom `x` étant déjà utilisé",
              "correct": false,
              "feedback": "Erreur : un paramètre peut porter le même nom qu'une variable\nextérieure, les deux restent indépendants.\n"
            }
          ],
          "explanation": "Le paramètre d'une fonction est une variable locale : même nom\nqu'une variable extérieure ou non, il vit séparément."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 2\n\ndef f(x):\n    return x + 1\n\nprint(f(20), x)\n```",
          "options": [
            {
              "text": "`21 2`",
              "correct": true,
              "feedback": "Bonne réponse : dans `f`, `x` est le paramètre et vaut 20,\nd'où 21. En dehors, `x` reste la variable initiale, 2.\n"
            },
            {
              "text": "`21 20`",
              "correct": false,
              "feedback": "Erreur : l'appel ne modifie pas la variable `x` extérieure.\n"
            },
            {
              "text": "`3 2`",
              "correct": false,
              "feedback": "Erreur : dans la fonction, `x` prend la valeur de l'argument,\n20, pas celle de la variable extérieure.\n"
            },
            {
              "text": "Une erreur, le nom `x` étant déjà utilisé",
              "correct": false,
              "feedback": "Erreur : un paramètre peut porter le même nom qu'une variable\nextérieure, les deux restent indépendants.\n"
            }
          ],
          "explanation": "Le paramètre d'une fonction est une variable locale : même nom\nqu'une variable extérieure ou non, il vit séparément."
        },
        {
          "statement": "Qu'affiche ce programme ?\n```python\nx = 9\n\ndef f(x):\n    return x + 1\n\nprint(f(1), x)\n```",
          "options": [
            {
              "text": "`2 9`",
              "correct": true,
              "feedback": "Bonne réponse : dans `f`, `x` est le paramètre et vaut 1,\nd'où 2. En dehors, `x` reste la variable initiale, 9.\n"
            },
            {
              "text": "`2 1`",
              "correct": false,
              "feedback": "Erreur : l'appel ne modifie pas la variable `x` extérieure.\n"
            },
            {
              "text": "`10 9`",
              "correct": false,
              "feedback": "Erreur : dans la fonction, `x` prend la valeur de l'argument,\n1, pas celle de la variable extérieure.\n"
            },
            {
              "text": "Une erreur, le nom `x` étant déjà utilisé",
              "correct": false,
              "feedback": "Erreur : un paramètre peut porter le même nom qu'une variable\nextérieure, les deux restent indépendants.\n"
            }
          ],
          "explanation": "Le paramètre d'une fonction est une variable locale : même nom\nqu'une variable extérieure ou non, il vit séparément."
        }
      ]
    },
    {
      "id": "q30",
      "difficulty": 3,
      "skills": [
        "fonction",
        "none",
        "erreur"
      ],
      "title": "Un résultat absent utilisé dans un calcul",
      "statement": "Que produit ce programme ?\n```python\ndef affiche(x):\n    print(x)\n\ny = affiche(2) + 1\n```",
      "options": [
        {
          "text": "`2` s'affiche, puis une erreur sur `None + 1`",
          "correct": true,
          "feedback": "Bonne réponse : l'appel affiche 2 et renvoie `None`. Le calcul\n`None + 1` échoue, car `None` n'est pas un nombre.\n"
        },
        {
          "text": "`2` s'affiche et `y` vaut `3`, la fonction renvoyant `x`",
          "correct": false,
          "feedback": "Erreur : la fonction n'a pas de `return`, elle ne renvoie pas 2.\n"
        },
        {
          "text": "Rien ne s'affiche et `y` vaut `3`, le `print` étant ignoré",
          "correct": false,
          "feedback": "Erreur : le `print` de la fonction s'exécute bien, puis\nl'addition échoue.\n"
        },
        {
          "text": "`3` s'affiche, l'addition étant faite avant l'affichage",
          "correct": false,
          "feedback": "Erreur : c'est `x`, égal à 2, qui est affiché, et aucun 3 n'est\ncalculé.\n"
        }
      ],
      "explanation": "Pour utiliser le résultat d'une fonction dans un calcul, il faut\nque la fonction le renvoie avec `return`. Un `print` seul ne suffit\npas."
    }
  ]
}