Ecrire des exercices Python
Nous verrons ici des exemples d'utilisation courantes de Pyodide-mkdocs-thème et de puzzle.
Les anciennes structures et syntaxes
Les anciennes structures et syntaxes (par exemple plusieurs fichiers séparés Python pour le sujet, la correction, les tests) utilisées avec l'ancien Pyodide sont encore opérantes. Si vous avez fait une mise à jour de votre site, il n'est pas nécessaire de les modifier. Elles peuvent cohabiter sur le même site avec les syntaxes présentées dans ce tutoriel.
Pour chaque exemple, vous pourrez copier le code correspondant, et l'adapter à votre guise.
Pour une documentation complète : Documentation détaillée de pyodide-mkdocs-theme par F. Zinelli
I. Présentation des exercices avec IDE⚓︎
Vous trouverez dans les paragraphes suivants des modèles de syntaxes à copier. Il s'agit ici de présenter les différentes possibilités.
Un exemple pour tester :⚓︎
- Cet exemple a été paramétré pour qu'au bout de 2 essais validés infructueux la réponse s'affiche.
- Dès que l'élève a réussi (vérification dans le fichier
exo.py
caché), la solution s'affiche, ainsi que les remarques contenues dans le fichierexo_REM.md
Question
La fonction somme
prend en paramètre une liste de nombres et renvoie la somme des nombres de cette liste.
Compléter le script ci-dessous :
-
⚠️ N'oubliez surtout pas de valider après avoir exécuté
-
Dans cet exercice, vous avez droit à deux essais validés :
Si les assert "ne passent pas", vous pouvez cliquer sur###
en haut à droite de la fenêtre avant de valider, pour que l'essai soit décompté. Au bout de deux essais validés, la solution s'affichera.
Les syntaxes⚓︎
Attention
Le fichier contenant les parties Python de votre exercice et l'éventuel fichier de remarques doivent se trouver dans le même dossier
que votre fichier .md
courant ou dans un dossier scripts
placé dans le même dossier que votre fichier .md
courant.
Il faudra juste veiller à indiquer les bons chemins vers vos fichiers.
Le fichier de remarques (facultatif) doit être nommé : mon_exo_REM.md (Ne pas oublier les majuscules)
Les différentes syntaxes à utiliser sont présentées ci-dessous, dans les différents onglets.
Des syntaxes courantes
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Le fichier nom_de_fichier_1.py
se trouvant dans le dossier scripts
est chargée dans l'IDE.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
nom_de_fichier_2
se trouvant dans le dossier scripts
dans un IDE avec division verticale.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
II. Exemple 1 - avec un IDE mais pas de fichier REM⚓︎
Par défaut les élèves peuvent valider leur exercice 5 fois avant que la correction ne s'affiche.
Exercice 1
Compléter le script ci-dessous (observer les assert
):
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichier utilisés pour cet exemple
# --- PYODIDE:code --- #
def accueil(prenom):
...
# --- PYODIDE:corr --- #
def accueil(prenom):
return "Bonjour " + prenom
# --- PYODIDE:tests --- #
assert accueil("Alice") == "Bonjour Alice"
assert accueil("Bob") == "Bonjour Bob"
# --- PYODIDE:secrets --- #
assert accueil("fegrehjtyjtqfqsgeryryrfg") == "Bonjour fegrehjtyjtqfqsgeryryrfg"
III. Exemple 2 - sans fonction - avec un IDE mais pas de fichier REM⚓︎
Dans cet exercice, on n'utilise pas de fonction.
Exercice 2
Compléter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichier utilisé pour cet exemple
# --- PYODIDE:code --- #
# un tableau cents en compréhension qui contient 10 entiers 100.
cents = ...
# un tableau entiers en compréhension qui contient les 10 entiers entre 1 et 10 compris.
entiers = ...
# --- PYODIDE:corr --- #
cents = [100 for k in range(10)]
entiers = [k for k in range(1, 11)]
# --- PYODIDE:tests --- #
assert cents == [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
assert entiers == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# --- PYODIDE:secrets --- #
assert cents == 10 * [100]
assert entiers == [k for k in range(1, 11)]
Attention à la section secrets
S'il y a une section # --- PYODIDE:corr --- #
ou un fichier de remarques comme exo_REM.md
Le fichier python doit absolument comporter la section :
# --- PYODIDE:secrets --- #
😢 En l'absence de la section # --- PYODIDE:secrets --- #
le pipeline sera mis en échec.
IV. Exemple 3, avec un IDE et un fichier REM⚓︎
Dans cet exemple on a utilisé la syntaxe : MAX = 2
. Les élèves pourront valider leur exercice seulement 2 fois avant que la correction ne s'affiche.
Le code à copier pour cet exemple se trouve plus bas ...
😊 Le code à copier n'a pas été oublié. Il se trouve après le rendu de l'exemple.
Exercice 3
- La fonction
est_pair
prend en paramètre un entier. - Elle renvoie
True
s'il est pair, etFalse
dans le cas contraire.
Compléter le script ci-dessous :
N'oubliez pas de valider après avoir exécuté.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichiers utilisés pour cet exemple
Deux fichiers ont été utilisés qui doivent se trouver dans le même dossier (ici scripts
)
Le contenu du fichier pair_REM.md
s'affiche automatiquement après la solution.
# --- PYODIDE:code --- #
def est_pair(nombre):
...
# --- PYODIDE:corr --- #
def est_pair(nombre):
return nombre % 2 == 0
# --- PYODIDE:tests --- #
assert est_pair(2)
assert est_pair(2000)
assert not est_pair(1)
assert not est_pair(777)
# --- PYODIDE:secrets --- #
assert est_pair(10**10)
assert not est_pair(10**10 + 1)
V. Exemple 4 avec un IDE et des "interdits" Python⚓︎
SANS
Dans cet exercice, nous allons utiliser la syntaxe SANS = "max, sorted, sort"
pour interdire l'utilisation de max
, ainsi que de sort
ou sorted
.
Le code à copier pour cet exemple
😊 Le code à copier n'a pas été oublié. Il se trouve après le rendu de l'exemple
Exercice 4
Écrire une fonction maximum
:
- prenant en paramètre une liste non vide de nombres :
nombres
- renvoyant le plus grand élément de cette liste.
Chacun des nombres utilisés est de type int
ou float
.
Contrainte
On interdit ici d'utiliser max
, ainsi que sort
ou sorted
.
Exemples
Compléter ci-dessous
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Écrire une fonction `maximum` :
- prenant en paramètre une liste **non vide** de nombres : `nombres`
- renvoyant le plus grand élément de cette liste.
Chacun des nombres utilisés est de type `int` ou `float`.
!!! danger "Contrainte"
On interdit ici d'utiliser `max`, ainsi que `sort` ou `sorted`.
???+ example "Exemples"
```pycon
>>> maximum([98, 12, 104, 23, 131, 9])
131
>>> maximum([-27, 24, -3, 15])
24
```
???+ question "Exercice 4"
Compléter ci-dessous
{{ IDE('scripts/maximum', SANS = "max, sorted, sort") }}
Fichiers utilisés pour cet exemple
# --- PYODIDE:code --- #
def maximum(nombres):
...
# --- PYODIDE:corr --- #
cents = [100 for k in range(10)]
entiers = [k for k in range(1, 11)]
# --- PYODIDE:tests --- #
assert maximum([98, 12, 104, 23, 131, 9]) == 131
assert maximum([-27, 24, -3, 15]) == 24
# --- PYODIDE:secrets --- #
assert maximum([1, 2, 3, 4, 5]) == 5
assert maximum([5, 4, 3, 2, 1]) == 5
assert maximum([5, 5, 5]) == 5
assert abs(maximum([5.01, 5.02, 5.0]) - 5.02) < 10**-6
assert maximum([-5, -4, -3, -8, -6]) == -3
assert maximum([1,2]) == 2
Documentation détaillée - Option SANS
VI. Exemple 5 avec un IDE et du code caché dans le sujet en Python⚓︎
Code caché
Dans cet exemple le fichier sujet en Python contient une partie qui n'est pas visible par l'élève.
Ces lignes de codes sont situées dans la section # --- PYODIDE:env --- #
Voir plus bas les fichiers utilisés dans cet exemple
???+ question "Exercice 5"
Vous ignorez le rôle de la fonction `mystere`, et vous ne voyez pas son code.
Vous allez donc utiliser la fonction `help` native en Python.
Compléter ci-dessous :
{{IDE('scripts/mystere_code_cache')}}
??? success "Solution"
```python
help(mystere)
```
Exercice 5
Vous ignorez le rôle de la fonction mystere
, et vous ne voyez pas son code.
Vous allez donc utiliser la fonction help
native en Python.
Compléter ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichiers utilisés pour cet exemple
# --- PYODIDE:env --- #
def mystere(nbre):
"""
La fonction prend en paramètre un nombre entier.
Elle renvoie True si ce nombre est un multiple de 7, False sinon
>>> mystere(21)
True
>>> mystere(22)
False
"""
return nbre % 7 == 0
# --- PYODIDE:code --- #
"""
La fonction mystere est cachée.
A vous d'en découvrir les spécifications
"""
Exercice sans validation ni correction
Cet exercice a été conçu sans tests et sans correction. Il a donc été ajouté une admonition ??? success "Solution"
pour
que la solution soit accessible.
Documentation détaillée - Les fichiers Python
VII. Exemple 6 avec une plus grande fenêtre pour l'IDE⚓︎
Modifier la taille de l'IDE
Parfois on voudrait que l'IDE affiche un plus grand nombre de lignes.
Il suffit d'utiliser la syntaxe (pour 55 lignes par exemple) IDE('exo', MAX_SIZE=55)
Exercice
Compléter le script ci-dessous :
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Documentation détaillée - L'option MAX_SIZE
VIII. Exemple 7 avec des questions imbriquées⚓︎
???+ question "Exercice à tiroirs"
**Question 1**
Compléter la fonction `est_pair` qui prend en paramètre un nombre entier `nbre`, et renvoie `True` s'il est pair, `False` sinon.
{{ IDE('scripts/parite') }}
**Question 2**
Compléter la fonction `filtre_pair` qui prend en paramètre un tableau de nombres entiers `entiers` et qui renvoie un nouveau tableau
ne contenant que les nombres pairs de `entiers`.
!!! danger "Contrainte"
Vous appelerez **obligatoirement** la fonction écrite à la question 1. Elle est dans le code caché de cette question. Vous n'êtes pas obligé
d'avoir réussi la question 1 pour répondre à cette question.
{{ IDE('scripts/filtre') }}
Exercice à tiroirs
Question 1
Compléter la fonction est_pair
qui prend en paramètre un nombre entier nbre
, et renvoie True
s'il est pair, False
sinon.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Question 2
Compléter la fonction filtre_pair
qui prend en paramètre un tableau de nombres entiers entiers
et qui renvoie un nouveau tableau
ne contenant que les nombres pairs de entiers
.
Contrainte
Vous appelerez obligatoirement la fonction écrite à la question 1. Elle est dans le code caché de cette question. Vous n'êtes pas obligé d'avoir réussi la question 1 pour répondre à cette question.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichiers utilisés pour cet exemple
# --- PYODIDE:code --- #
def est_pair(nombre):
...
# --- PYODIDE:corr --- #
def est_pair(nombre):
return nombre % 2 == 0
# --- PYODIDE:tests --- #
assert est_pair(2) is True
assert est_pair(2000) is true
assert est_pair(1) is False
assert est_pair(777) is False
# --- PYODIDE:secrets --- #
assert est_pair(10**10) is True
assert est_pair(10**10 + 1) is False
assert est_pair(0) is True
# --------- PYODIDE:env --------- #
def est_pair(n):
return n % 2 == 0
# --------- PYODIDE:code --------- #
def filtre_pair(entiers):
...
# --------- PYODIDE:corr --------- #
def filtre_pair(entiers):
return [nbre for nbre in entiers if est_pair(nbre)]
# --------- PYODIDE:tests --------- #
assert filtre_pair([1, 2, 3, 4, 5, 6, 7]) == [2, 4, 6]
assert filtre_pair([]) == []
# --------- PYODIDE:secrets --------- #
assert filtre_pair([100, 201, 302, 404, 501, 601, 700]) == [100, 302, 404, 700]
IX. Exercice en deux versions⚓︎
Compléter la fonction `dernier` qui prend en paramètre une liste de nombres `ma_liste`, et renvoie le dernier élément de cette liste.
=== "Version vide"
{{ IDE('scripts/exo_vide') }}
=== "Version à compléter"
{{ IDE('scripts/exo_trous') }}
Compléter la fonction dernier
qui prend en paramètre une liste de nombres ma_liste
, et renvoie le dernier élément de cette liste.
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Fichiers utilisés pour cet exemple
# --------- PYODIDE:code --------- #
def dernier(ma_liste):
...
# --------- PYODIDE:corr --------- #
def dernier(ma_liste):
return ma_liste[len(ma_liste) - 1]
# --------- PYODIDE:tests --------- #
assert dernier([1]) == 1
assert dernier([3, 4, 5]) == 5
# --------- PYODIDE:secrets --------- #
assert dernier([5, 4, 3]) == 3
# --------- PYODIDE:code --------- #
def dernier(ma_liste):
return ma_liste[len( ...) - ...]
# --------- PYODIDE:corr --------- #
def dernier(ma_liste):
return ma_liste[len(ma_liste) - 1]
# --------- PYODIDE:tests --------- #
assert dernier([1]) == 1
assert dernier([3, 4, 5]) == 5
# --------- PYODIDE:secrets --------- #
assert dernier([5, 4, 3]) == 3
X. Exercice avec la réponse à chercher ailleurs (avec un lien interne)⚓︎
La réponse est à chercher en suivant un lien
???+ question
Comment fait-on une admonition "note pliée" ?
??? success "Solution"
Vous pouvez trouver la réponse ici : [admonitions](../02_basique/2_page_basique.md)
On indique juste le nom du fichier s'il est dans le même dossier.
Question
Comment fait-on une admonition "note pliée" ?
Solution
Vous pouvez trouver la réponse ici : admonitions
On indique juste le nom du fichier s'il est dans le même dossier.
XI. Cause fréquente de pannes :⚓︎
Sections vides
Il ne faut pas de section vide dans le fichier python d'un exercice :
Ceci mettra le pipeline en échec :
Si on n'a pas besoin d'une section, on ne l'écrit pas :
absence de la section secrets
Si votre exercice contient une section # --- PYODIDE:corr --- #
, ou un fichier de remarque comme exo_REM.md
mais pas de section # --- PYODIDE:secrets --- #
, cela mettra le pipeline en échec.
Modifier ces comportements?
Il est possible de changer ce type de comportement en modifiant la configuration du plugin pyodide_macros
, dans le fichier mkdocs.yml
.
Les options généralement en jeu sont les suivantes (passer à false
celle qui vous concerne, si vous souhaitez autoriser le comportement en question) :
plugins:
- pyodide_macros
ides:
forbid_secrets_without_corr_or_REMs: true
forbid_hidden_corr_and_REMs_without_secrets: true
forbid_corr_and_REMs_with_infinite_attempts: true
Voir la documentation détaillée pour des informations sur les différentes options.
XII. Insérer une section d'un fichier python d'exercice⚓︎
Contenu du fichier mystere_section.py
# --- PYODIDE:env --- #
def mystere(nbre):
"""
La fonction prend en paramètre un nombre entier.
Elle renvoie True si ce nombre est un multiple de 7, False sinon
>>> mystere(21)
True
>>> mystere(22)
False
"""
return nbre % 7 == 0
# --- PYODIDE:code --- #
"""
La fonction mystere est cachée.
A vous d'en découvrir les spécifications
"""
...
# --- PYODIDE:corr --- #
help(mystere)
On peut faire afficher dans la page en cours n'importe quelle section se trouvant dans ce fichier.
La macro section
* Voici la fonction `mystere` qui se trouve dans le code caché
{{ section('scripts/mystere_section', 'env') }}
* Voici la correction de cet exercice
{{ section('scripts/mystere_section', 'corr') }}
- Voici la fonction
mystere
qui se trouve dans le code caché :
Python | |
---|---|
- Voici la correction de cet exercice :
Python | |
---|---|
Documentation détaillée - macro section
XIII. Site de référence pour toutes les syntaxes et d'autres possibilités⚓︎
Seules les possibilités les plus couramment utilisées ont été expliquées dans ce tutoriel. Il en existe d'autres :
Documentation détaillée de pyodide-mkdocs-theme par F. Zinelli
XIV. Exemple de puzzle⚓︎
Site pour créer les puzzles : Création de puzzles
Cliquer sur le menu en haut à droite (plier/déplier) pour recopier le code à insérer.
La réponse attendue est `cinq = [5 for k in range(20)]`
???+ question
<iframe src="https://www.codepuzzle.io/p/T3WK" width="100%" height="300" frameborder="0"></iframe>
Rendu :
La réponse attendue est cinq = [5 for k in range(20)]
# Tests
(insensible à la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)