Compare commits
2 commits
f6d545059f
...
dbc42bcf59
| Author | SHA1 | Date | |
|---|---|---|---|
| dbc42bcf59 | |||
| 51d6511426 |
7 changed files with 396 additions and 479 deletions
|
|
@ -8,10 +8,13 @@ Il en existe un très grand nombre, mais il est aussi très courant que les dév
|
|||
Qu'est-ce qu'une fonction ?
|
||||
|
||||
```admonish success title="Définition"
|
||||
Une fonction exécute une suite d'instructions pour réaliser une action précise. Elle possède un nom par lequel on peut l'appeler, pour réaliser cette suite d'instructions.
|
||||
Une fonction est un sous-programme (c'est à dire une suite d'instructions) permettant d'effectuer des actions que l'on souhaite répéter.
|
||||
- Elle possède un nom par lequel on peut l'appeler
|
||||
- Elle peut prendre des paramètres en entrée
|
||||
- Elle peut renvoyer des données en sortie
|
||||
```
|
||||
|
||||
Autrement dit, une fonction exécute un ensemble d'actions pré-enregistrées, auxquelles on a donné un nom pour pouvoir réaliser ces actions plus facilement, sans avoir à toujours les répéter.
|
||||
Autrement dit, une fonction exécute un ensemble d'actions pré-enregistrées, auxquelles on a donné un nom pour pouvoir réaliser ces actions plus facilement, sans avoir à toujours les répéter. On peut lui passer des informations nécessaires à son exécution, et elle peut nous renvoyer un résultat.
|
||||
|
||||
### Appeler une fonction
|
||||
|
||||
|
|
@ -30,10 +33,10 @@ nom_de_la_fonction(parametre_1, parametre_2, ...., parametre_n)
|
|||
|
||||
#### Paramètres
|
||||
|
||||
Les paramètres sont des données que l'ont fournit à la fonction pour qu'elle puisse adapter son résultat à notre besoin.
|
||||
Les paramètres sont des données que l'ont fournit à la fonction pour qu'elle puisse adapter son résultat à notre besoin. Ils sont généralement d'un ou plusieurs types définis, qui dépendent de la fonction utilisée.
|
||||
|
||||
```admonish example title="Exemple"
|
||||
La fonction `print` affiche une chaîne de caractères. On lui passe la chaîne que l'on veut afficher en paramètre :
|
||||
La fonction `print` affiche une chaîne de caractères. On lui passe donc la chaîne que l'on veut afficher en paramètre, de type `str` :
|
||||
~~~python
|
||||
# Pour afficher "Hello, World!", on passe en paramètre "Hello, World!" à print
|
||||
print("Hello, World!")
|
||||
|
|
@ -125,6 +128,14 @@ Les paramètres peuvent être optionnels. Pour cela, il faut qu'ils aient une **
|
|||
|
||||
La valeur par défaut est la valeur que prend le paramètre si on ne lui en fournit aucune autre.
|
||||
|
||||
Pour ajouter une valeur par défaut à un paramètre, on utilise la syntaxe suivante :
|
||||
|
||||
```python
|
||||
def ma_fonction(parametre=valeur_par_defaut): # valeur_par_defaut peut être de n'importe quel type : on peut mettre une chaine de caractères, un entier, un flottant, ...
|
||||
# Mon code ici
|
||||
```
|
||||
|
||||
|
||||
```admonish example title="Exemple"
|
||||
~~~python
|
||||
def ma_fonction(parametre="valeur par défaut"):
|
||||
|
|
@ -134,6 +145,14 @@ ma_fonction()
|
|||
# Résultat affiché : valeur par défaut
|
||||
ma_fonction(parametre="Autre valeur")
|
||||
# Résultat affiché : Autre valeur
|
||||
|
||||
## Autres exemples
|
||||
def ma_fonction(parametre=3):
|
||||
# Mon code ici
|
||||
|
||||
def ma_fonction(parametre=True):
|
||||
# Mon code ici
|
||||
|
||||
~~~
|
||||
```
|
||||
|
||||
|
|
@ -152,6 +171,10 @@ def add(a, b):
|
|||
~~~
|
||||
```
|
||||
|
||||
```admonish warning title="Important"
|
||||
Le code se trouvant **après** l'instruction `return` dans une fonction ne sera jamais exécuté
|
||||
```
|
||||
|
||||
#### Bonnes pratiques
|
||||
|
||||
- Faites des fonctions courtes qui vont à l'essentiel (20 lignes est un bon maximum)
|
||||
|
|
@ -161,7 +184,12 @@ def add(a, b):
|
|||
Exemple:
|
||||
```python
|
||||
def ma_fonction(arg_1, arg2):
|
||||
"""Ceci est une docstring qui vient documenter ma fonction.
|
||||
"""Ceci est une docstring simple documenter ma fonction."""
|
||||
```
|
||||
|
||||
```python
|
||||
def ma_fonction(arg_1, arg2):
|
||||
"""Ceci est une docstring au format Numpy qui vient documenter ma fonction.
|
||||
|
||||
Une docstring peut prendre plusieurs lignes. Une bonne docstring vient expliquer les arguments
|
||||
et ce que renvoie la fonction.
|
||||
|
|
@ -179,5 +207,78 @@ def add(a, b):
|
|||
Retourne un booléen pour l'exemple
|
||||
"""
|
||||
# Bloc d'instructions
|
||||
return True
|
||||
```
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
Il existe de nombreuses fonctions fournies avec Python, de base. Pourtant, il est tout de même possible de rajouter de très nombreuses
|
||||
fonctionnalités à nos programmes en important des modules.
|
||||
|
||||
### Qu'est-ce qu'un module ?
|
||||
|
||||
Un module, c'est du code que l'on a écrit dans un fichier. En général, on rassemble au même endroit
|
||||
des fonctions, variables, constantes etc.. ayant un rapport entre elles dans un seul et même fichier.
|
||||
|
||||
Cela permet d'**importer** toutes les fonctionnalités du module en une seule fois et de pouvoir les utiliser. On dit programme que l'on veut utiliser les fonctionnalités du module en l'important.
|
||||
|
||||
Les modules sont pratiques pour plusieurs choses :
|
||||
- Partager du code entre développeurs : certaines fonctionnalités peuvent servir à d'autres, et les modules permettent de facilement réutiliser le code
|
||||
- Découper un programme en portions plus petites, et qui ont un lien entre elles, de façon à le rendre plus digeste, ou réutiliser certaines portions à plusieurs endroits ou dans plusieurs programmes
|
||||
|
||||
### Importer un module
|
||||
|
||||
Pour importer (c'est à dire utiliser) un module, on peut utiliser l'instruction `import` suivi du nom du module.
|
||||
|
||||
```admonish example title="Exemple"
|
||||
Pour utiliser tout un tas de fonctions mathématiques, on peut importer le module `math`
|
||||
~~~python
|
||||
import math
|
||||
~~~
|
||||
```
|
||||
|
||||
Après un import, en apparence rien ne se passe, mais en réalité le programme vient de rendre toutes les fonctions du module accessibles. On peut ensuite appeler une fonction en la précédant du nom du module suivi d'un point.
|
||||
|
||||
```admonish example title="Exemple"
|
||||
Pour utiliser la fonction racine carrée (`sqrt` pour square root) du module `math` et calculer la racine carrée de 16:
|
||||
~~~python
|
||||
import math
|
||||
|
||||
math.sqrt(16)
|
||||
|
||||
# Resultat : 4
|
||||
~~~
|
||||
```
|
||||
|
||||
Il existe une autre syntaxe, si on ne veut pas importer la totalité du module, mais seulement une fonction choisie : `from ... import ...`. La fonction peut alors être utilisée sans le nom du module.
|
||||
|
||||
```admonish example title="Exemple"
|
||||
Pour utiliser la fonction racine carrée (`sqrt` pour square root) du module `math` et calculer la racine carrée de 16, mais cette fois avec la syntaxe `from ... import ...`:
|
||||
~~~python
|
||||
from math import sqrt
|
||||
|
||||
sqrt(16)
|
||||
|
||||
# Resultat : 4
|
||||
~~~
|
||||
```
|
||||
|
||||
### Créer un module
|
||||
|
||||
Pour créer un module, rien de plus simple : il suffit de créer un nouveau fichier.
|
||||
|
||||
Le fichier devra :
|
||||
- Avoir un nom en minuscules
|
||||
- se terminer par l'extension `.py`
|
||||
|
||||
Et on pourra alors importer le module en utilisant son nom (sans l'extension `.py`).
|
||||
|
||||
```admonish example title="Exemple"
|
||||
Pour utiliser le module `mon_module.py`, dans lequel se trouve `ma_fonction`, on pourra écrire
|
||||
~~~python
|
||||
import mon_module
|
||||
|
||||
### Ou encore
|
||||
|
||||
from mon_module import ma_fonction
|
||||
~~~
|
||||
```
|
||||
|
|
|
|||
109
src/cours/CIEL1/01-bases-python/dm/tp1bis_mise_en_pratique.md
Normal file
109
src/cours/CIEL1/01-bases-python/dm/tp1bis_mise_en_pratique.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Python - Mise en pratique
|
||||
|
||||
Nous allons mettre en pratique ce que nous avons vu jusqu'à maintenant dans un programme un peu plus conséquent.
|
||||
|
||||
L'objectif est de créer un mini jeu dans lequel vous pourrez jouer à la roulette. Les règles seront évidemment simplifiées.
|
||||
|
||||
- Le joueur mise sur un nombre (entier) entre 0 et 49, et annonce une mise en jetons (par exemple : 20 jetons).
|
||||
- La croupière lance la roulette, et celle-ci déterminera le numéro gagnant. Les numéros impairs ont une couleur rouge, les numéros pairs sont noirs.
|
||||
- Si le joueur a misé sur le numéro gagnant, il remporte 3 fois sa mise
|
||||
- Si le joueur a misé sur un nombre de même couleur (donc de même parité que le numéro gagnant), il remporte 0,5 fois sa mise (arrondi à l'entier supérieur, car les jetons sont toujours entiers)
|
||||
- Sinon, le joueur perd sa mise. Notons qu'il la garde dans les deux autres cas, en plus de ses gains.
|
||||
- Le joueur aura 100 jetons disponibles au début de la partie. Il ne peut miser qu'un nombre entier de jeton, et seulement des jetons qu'il possède.
|
||||
- Si le joueur tombe à zéro jetons, la partie est finie.
|
||||
- Sinon, il peut rejouer (mais n'est pas obligé).
|
||||
|
||||
Imprégnez-vous bien des règles du jeu.
|
||||
|
||||
1. Créez un nouveau fichier appelé `roulette.py`.
|
||||
2. Copiez le contenu suivant dedans. Ce sera la structure du script, que vous complèterez à l'aide des questions suivantes.
|
||||
|
||||
Il y a de nombreux `#TODO` (parfois `"#TODO"`) qu'il faudra remplacer par le code adéquat.
|
||||
|
||||
L'instruction `pass` sert à ne rien faire tout en ayant un script valide qui pourra donc s'exécuter sans erreur pour que vous puissiez avancer et tester votre code. Vérifiez que le code ci-dessous fonctionne sans erreur (il ne fera évidemment pas ce qui est demandé, ça c'est votre job !)
|
||||
|
||||
~~~python
|
||||
from random import randint
|
||||
#TODO
|
||||
|
||||
def miser(jetons_restants):
|
||||
#TODO
|
||||
return 7, 12
|
||||
|
||||
def choisir_nombre():
|
||||
nombre = -1
|
||||
while "#TODO condition" :
|
||||
nombre = "#TODO demander un nombre à l'utilisatrice"
|
||||
if "#TODO condition":
|
||||
print("Erreur : le nombre doit être compris entre 0 et 49")
|
||||
return nombre
|
||||
|
||||
#TODO fonction miser_jetons
|
||||
|
||||
def tourner_la_roulette():
|
||||
numero = 8 #TODO
|
||||
print(f"Le croupier tourne la roulette. Le numéro {numero} est le numéro gagnant !")
|
||||
return numero
|
||||
|
||||
def calculer_gains_couleur(mise):
|
||||
pass #TODO
|
||||
|
||||
def calculer_gains_numero(mise):
|
||||
pass #TODO
|
||||
|
||||
def continuer_de_jouer(jetons_restants):
|
||||
return #TODO Effacer cette ligne quand ce sera demandé
|
||||
if "#TODO condition":
|
||||
print("Vous êtes ruiné.e. C'est la fin de la partie.")
|
||||
#TODO Retourner une valeur
|
||||
else:
|
||||
#TODO Afficher les jetons restants (avec une phrase)
|
||||
rejouer = input("Souhaitez-vous continuer ? (o/n)")
|
||||
if rejouer == "o" or rejouer == "O":
|
||||
pass #TODO Retourner une valeur
|
||||
else:
|
||||
#TODO Annoncer qu'on quitte le jeu avec le nombre de jetons restants
|
||||
pass #TODO Retourner une valeur
|
||||
|
||||
jetons = 100
|
||||
continuer = True
|
||||
|
||||
while continuer:
|
||||
gains = 0
|
||||
numero_misé, mise = miser(jetons)
|
||||
|
||||
numero_gagnant = tourner_la_roulette()
|
||||
#TODO Écrire ici la condition principale, pour déterminer les gains
|
||||
|
||||
jetons += gains
|
||||
continuer = continuer_de_jouer(jetons)
|
||||
~~~
|
||||
|
||||
3. Expliquez les étapes du programme qui se déroulent dans la boucle à la fin du script, et quand est-ce qu'elle s'arrête.
|
||||
1. Complétez les fonctions suivantes à l'aide des règles du jeu :
|
||||
1. `calculer_gains_numero`
|
||||
1. `calculer_gains_couleur`. Comme nous voulons arrondir à l'entier supérieur, il faudra importer et utiliser la fonction `ceil` du module `math`.
|
||||
|
||||
Pour vérifier vos résultats, vous pouvez soit utiliser l'interpréteur en console, soit appeler les fonctions dans votre script et utiliser `print` pour afficher le résultat
|
||||
|
||||
2. Allez à la ligne `#TODO Écrire ici la condition principale, pour déterminer les gains`. Cette condition est celle qui permet de savoir si un joueur a gagné ou non.
|
||||
1. Écrivez la condition en utilisant les fonctions `calculer_gains_couleur` et `calculer_gains_numero`. N'oubliez pas le cas où le joueur perd.
|
||||
2. Ajoutez des `print` dans chaque branche pour annoncer les gains ou pertes.
|
||||
3. Testez les différents cas possibles en modifiant les valeurs retournées par la fonction `tourner_la_roulette`
|
||||
1. Maintenant que nous sommes sûrs que nos trois cas fonctionnent, nous allons pouvoir réellement tirer un nombre au hasard. Pour cela, nous avons déjà importé la fonction `randint` du module `random` dont voici la [documentation](https://docs.python.org/3.13/library/random.html#random.randint) :
|
||||
> random.**randint**(a, b)
|
||||
>
|
||||
> Return a random integer N such that a <= N <= b. Alias for randrange(a, b+1).
|
||||
|
||||
1. Expliquez brièvement ce que fait `randint`
|
||||
2. Modifiez la fonction `tourner_la_roulette` de façon à ce qu'elle retourne un nombre entre 0 et 49 tiré aléatoirement.
|
||||
|
||||
1. Le coeur du jeu semble maintenant fonctionner. Il ne reste plus qu'à permettre à la joueuse d'interagir avec le programme. Commençons par la mise.
|
||||
1. Complétez la fonction `choisir_nombre` de façon à ce que l'on demande à la joueuse un nombre tant que celui-ci n'est pas valide. Pour simplifier, considérons que personne ne s'amusera à entrer autre chose que des nombres (nous verrons plus tard dans l'année un moyen bien plus efficace de gérer les erreurs).
|
||||
2. Complétez la fonction `miser` pour qu'elle utilise notre fonction nouvellement complétée. Vérifiez que tout fonctionne comme prévu.
|
||||
3. Sur le même modèle que `choisir_nombre`, écrivez une fonction `miser_jetons` qui permettra à la joueuse de choisir un nombre de jetons à miser. Attention : il faudra vérifier qu'elle ne mise pas plus de jetons que ce qu'elle a. Vous aurez donc besoin d'un paramètre pour passer le nombre de jetons restants à votre fonction.
|
||||
4. Complétez la fonction `miser` pour qu'elle utilise notre nouvelle fonction. Vérifiez que tout fonctionne comme prévu.
|
||||
|
||||
1. Maintenant, il ne reste plus qu'à demander au joueur s'il souhaite continuer de jouer, et mettre fin à la partie s'il n'a plus de jetons. Dans la fonction `continuer_de_jouer`, retirez la première ligne, celle qui contient un `return`. Complétez le reste de la fonction en remplaçant les lignes contenant la mention `#TODO`. Testez votre programme de bout en bout.
|
||||
|
||||
1. Mettez le programme final dans votre compte rendu.
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
# Python - Les fonctions
|
||||
|
||||
Dans le précédent TP vous avez vu les bases du langage Python. Vous les avez mises en pratique dans de petits programmes, et vous savez maintenant gérer des variables, des structures conditionnelles et des structures répétitives (les boucles). Vous pouvez déjà faire beaucoup de choses en Python avec ça.
|
||||
|
||||
Dans ce TP, nous allons commencer à utiliser Visual Studio Code, qui nous servira toute l'année d'éditeur de texte pour la plupart des TP. Ensuite, nous verrons une notion indispensable à tous les langages de programmation : les fonctions. Nous en profiterons pour réutiliser les notions du TP précédent pour continuer de les pratiquer et, petit à petit, mieux les maîtriser. Vous écrirez, pas à pas, un programme plus conséquent que ce que vous avez écrit jusqu'à maintenant.
|
||||
|
||||
## 1 - Utilisation de Visual Studio Code
|
||||
|
||||
### 1.1 - Mise en route
|
||||
|
||||
Pour ce TP nous n'allons plus utiliser Thonny mais Visual Studio Code. Thonny est un excellent logiciel pour débuter en python, et il sera facile à utiliser pour vous entraîner à la maison, mais il n'est pas beaucoup utilisé par les professionnels car il manque de fonctionnalités indispensables. Visual Studio Code est un éditeur de texte libre édité par Microsoft, compatible avec toutes les plateformes. Il permet de faire ce que fait Thonny, mais également plein d'autres choses. C'est un logiciel très utilisé en entreprise et pourra vous servir pour de nombreux langages de programmation. C'est pour cela que nous allons commencer à l'utiliser, et vous vous habituerez à son fonctionnement au fil du temps.
|
||||
|
||||
Lancez Visual Studio Code depuis le menu démarrer de votre machine. Vous verrez une interface comme ci-dessous. Sur la capture d'écran, les sections dont vous aurez besoin lors de ce TP sont indiquées par des flèches.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
```admonish travail
|
||||
- Ouvrez un répertoire : créez un sous-répertoire dans votre espace personnel, sous `projets/python/tp2_fonctions/` et selectionnez-le. Cochez la case et cliquez sur `Yes, I trust the authors` si la fenêtre ci-dessous s'ouvre.
|
||||

|
||||
- Vérifiez dans le menu extensions que l'extension Python proposée par Microsoft soit bien installée. Sinon, recherchez-la dans la barre de recherche du menu des extensions et installez-la.
|
||||
|
||||

|
||||
|
||||
Cette extension vous permettra d'avoir une coloration syntaxique ainsi que des suggestions pour écrire le code qui vous seront très utiles. Elle vous permettra aussi de détecter des erreurs de syntaxe, ce qui pourra vous permettre de progresser plus vite.
|
||||
- Ouvrez l'explorateur. Vous verrez qu'il n'y a aucun fichier, ce qui est normal. Nous en créerons un tout à l'heure.
|
||||
- Ouvrez le menu Terminal, et cliquez sur `Nouveau terminal`. Vous verrez apparaître un volet en bas avec un terminal prêt à l'emploi.
|
||||
|
||||

|
||||
|
||||
- Dans le terminal, tapez la commande `python`. Vous verrez apparaître l'invite de commande de l'interpréteur python. Vous pourrez l'utiliser pour essayer des commandes python au cours du TP. En attendant, essayez de taper `print("Hello, World!")` dans l'interpréteur pour vérifier que tout fonctionne.
|
||||
|
||||

|
||||
|
||||
- Dans l'explorateur, faites un clic droit et créez un nouveau fichier que vous appellerez `main.py`. Dans ce fichier, ajoutez la ligne `print("Hello, World!")`.
|
||||

|
||||
- Via l'explorateur Windows, allez dans le répertoire de travail que vous avez sélectionné à la première étape. Vous y trouverez votre fichier main.py nouvellement créé : l'explorateur de VSCode montre le contenu de votre répertoire de travail. Mais vous l'avez toujours sous les yeux, ce qui est bien plus pratique.
|
||||
- Dans un nouveau terminal (vous pouvez cliquer sur le petit + en haut à droite du volet terminal actuel) tapez `python main.py`. Vous devriez voir s'afficher `Hello, World!` dans le terminal.
|
||||

|
||||
|
||||
- Cliquez maintenant sur le triangle en haut à droite de votre fichier. Vous devriez voir un nouveau terminal s'ouvrir et votre script sera exécuté. Vous connaissez maintenant deux méthodes pour lancer un script Python dans VSCode.
|
||||
|
||||

|
||||
|
||||
Remarquez que dans ce second cas, VSCode utilise des chemins absolus (depuis `C:/`), tandis que vous avez utilisé un chemin relatif (depuis le répertoire de travail).
|
||||
|
||||
Nous voilà prêts à travailler.
|
||||
```
|
||||
|
||||
## 2 - Les fonctions
|
||||
|
||||
### 2.1 - Utilisation d'une fonction
|
||||
|
||||
Nous allons maintenant écrire un script que nous modifierons pour découvrir les fonctions.
|
||||
|
||||
Vous connaissez déjà certaines fonctions, celles que vous avez utilisées lors du précédent TP : `print`, `input`, `math.sqrt`, `range` ... Ce sont des fonctions que vous avez **appelées** mais qui existent déjà, soit par défaut dans le langage Python, soit dans une bibliothèque (`math`).
|
||||
|
||||
```admonish travail
|
||||
1. Copiez le script suivant dans votre fichier `main.py`. Indiquez les fonctions que vous identifiez.
|
||||
|
||||
~~~python
|
||||
import math
|
||||
|
||||
nb = 7
|
||||
|
||||
print("Table par 7 : ")
|
||||
for i in range(1, 11):
|
||||
print(f"{i} * {nb}", "=", i*nb)
|
||||
|
||||
racine_carree = math.sqrt(7)
|
||||
retour_print = print(f"Racine carrée de {nb} : {racine_carree}")
|
||||
~~~
|
||||
|
||||
1. Indiquez les symboles utilisés pour appeler des fonctions.
|
||||
1.
|
||||
1. Quels sont les **arguments** (ou **paramètres**) passés à la fonction `range` ligne 6 ?
|
||||
1. Quel symbole sert à les séparer ?
|
||||
1. Que se passe-t-il si on retire ce symbole ?
|
||||
1.
|
||||
1. Modifiez l'ordre des arguments passés à `print` ligne 7. Qu'est-ce que ça change ?
|
||||
1. Ajoutez à la fonction `print` ligne 7 un argument `sep='-'`. Réexécutez le script. Qu'est-ce que ça change ?
|
||||
1. Ajoutez maintenant un argument `end='|'` à la fonction `print` ligne 7. Réexécutez le script. Qu'est-ce que ça change ?
|
||||
1. Expliquez selon vous ce que font les paramètres `sep` et `end` de la fonction `print`
|
||||
1. Inversez l'ordre des paramètres `sep` et `end` entre les parenthèses. Qu'est-ce que ça change ? À votre avis pourquoi ?
|
||||
1.
|
||||
1. Quelle est la valeur de la variable `racine_carree` à la fin du script ? D'où vient cette valeur ?
|
||||
1. Quelle est la valeur de la variable `retour_print` à la fin du script ? À votre avis pourquoi ?
|
||||
```
|
||||
|
||||
```admonish success title="À retenir"
|
||||
- Les fonction s'utilisent avec la syntaxe suivante : `nom_de_la_fonction(parametre_1, parametre_2, ...., parametre_n)`
|
||||
- Vous mettez le nom de la fonction, suivi de parenthèses
|
||||
- Entre les parenthèses vous mettez les paramètres séparés par des virgules
|
||||
- Si une fonction n'a pas besoin de paramètres, les parenthèses sont quand même indispensables
|
||||
|
||||
- Certaines fonctions peuvent prendre des paramètres nommés, avec la syntaxe suivante : `nom_de_la_fonction(nom_parametre=valeur_parametre)`. Les paramètres nommés sont toujours à la fin et leur ordre n'a pas d'importance.
|
||||
|
||||
- Une fonction peut renvoyer un résultat, que l'on peut alors affecter à une variable.
|
||||
- Si une fonction ne renvoie rien, alors elle renverra en réalité la valeur spéciale `None`.
|
||||
```
|
||||
|
||||
### 2.2 - Créer notre première fonction
|
||||
|
||||
Maintenant que vous savez comment utiliser une fonction nous allons créer une fonction par nous-mêmes.
|
||||
|
||||
Si on reprend le code de la partie précédente, on voit qu'il permet d'afficher la table de multiplication par 7. Nous allons en faire une fonction.
|
||||
|
||||
```admonish travail
|
||||
1. Remplacez le contenu de votre fichier main.py par le code qui suit. C'est le même que dans la partie précédente, débarrassé des choses qui ne servent pas à calculer notre table de 7. Vérfiez qu'il affiche correctement ce que vous attendez.
|
||||
~~~python
|
||||
nb = 7
|
||||
|
||||
print("Table par 7 : ")
|
||||
for i in range(1, 11):
|
||||
print(f"{i} * {nb}", "=", i*nb)
|
||||
~~~
|
||||
2. Une fonction se définit de la manière suivante :
|
||||
~~~python
|
||||
def nom_de_la_fonction(parametre_1, parametre_2, ..., parametre_n):
|
||||
# Instructions
|
||||
~~~
|
||||
- On utilise le mot-clé `def` suivi du nom de la fonction.
|
||||
- Entre parenthèses on ajoute les paramètres qu'il faudra fournir
|
||||
- à la fin de la ligne on met `:` (encore et toujours)
|
||||
- On passe à la ligne suivante et on indente pour écrire les instructions.
|
||||
|
||||
Modifiez le code pour mettre le contenu au dessus dans une fonction, comme ci-dessous. Puis exécutez-le. Que se passe-t-il ? A votre avis, pourquoi ?
|
||||
~~~python
|
||||
def table_par_7():
|
||||
nb = 7
|
||||
|
||||
print("Table par 7 : ")
|
||||
for i in range(1, 11):
|
||||
print(f"{i} * {nb}", "=", i*nb)
|
||||
~~~
|
||||
3. Il faut en réalité appeler notre fonction maintenant. En 2. elle était uniquement déclarée, Python connaissait son existence. Mais nous ne lui avons jamais dit de l'utiliser.
|
||||
1. Ajoutez alors la ligne `table_par_7()` à la toute fin du fichier. Exécutez le code et vérifiez que cette fois, tout se passe comme prévu.
|
||||
2. Déplacez cette ligne tout en haut du fichier. Que se passe-t-il ? Pourquoi à votre avis ?
|
||||
3. Replacez la ligne à la fin du fichier, comme en 3.1.
|
||||
|
||||
4. Bon, maintenant nous avons une fonction qui fait la même chose qu'avant. Mais si on veut calculer la table par 5 ou 8, il nous faudrait pouvoir passer la valeur en paramètre.
|
||||
1. Renommez la fonction en `table`, puisqu'elle nous servira à d'autres tables que celle par 7
|
||||
2. Ajoutez un argument `nb` dans la définition et retirez la variable `nb = 7`
|
||||
~~~python
|
||||
def table(nb):
|
||||
print(f"Table par {nb} : ")
|
||||
for i in range(1, 11):
|
||||
print(f"{i} * {nb}", "=", i*nb)
|
||||
~~~
|
||||
3. Maintenant, donnez le code nécessaire pour afficher la table par 5. Vérifiez que cela fonctionne bien dans votre script.
|
||||
5. Ajoutez un nouveau paramètre `maximum` qui servira à déterminer le nombre de lignes à afficher. Par exemple, si `nb` vaut 5 et `maximum` vaut 20, on affichera la table de 5 avec les valeurs de 1 à 20.
|
||||
|
||||
Modifiez les appels à votre fonction en conséquence et vérifiez que tout fonctionne comme prévu.
|
||||
|
||||
Mettez le code dans votre compte rendu.
|
||||
|
||||
6. Dans la majorité des cas on voudra probablement afficher la table jusqu'à 10. Pour nous éviter de devoir préciser `maximum` à chaque fois, nous allons mettre une valeur par défaut à `maximum` pour que la fonction affiche les 10 premières lignes si le paramètre n'est pas précisé.
|
||||
|
||||
Pour cela ajoutez simplement `=10` dans la déclaration de la fonction, à côté de l'argument `maximum`. Cela affectera la valeur 10 à `maximum` si rien n'est précisé.
|
||||
|
||||
Exécutez votre fonction avec `table(5, 20)` puis `table(7)` et vérifiez que nous avons bien la table par 5 de 1 à 20 dans le premier cas, et la table par 7 de 1 à 10 dans le second
|
||||
|
||||
7. Copiez le code suivant à la suite de votre fichier, puis exécutez-le. Quelle est la dernière ligne qui s'affiche ? À votre avis pourquoi ?
|
||||
~~~python
|
||||
def exemple():
|
||||
print("Ma première fonction d'exemple")
|
||||
|
||||
def exemple():
|
||||
print("Ma deuxième fonction d'exemple")
|
||||
|
||||
exemple()
|
||||
~~~
|
||||
```
|
||||
|
||||
```admonish success title='À retenir'
|
||||
- Les fonctions servent à rendre votre code plus clair et mieux découpé. Elles permettent de réutiliser du code.
|
||||
- Pour déclarer une fonction en python :
|
||||
~~~python
|
||||
def nom_de_la_fonction(parametre_1, parametre_2, ..., parametre_n):
|
||||
# Instructions
|
||||
~~~
|
||||
- On utilise le mot-clé `def` suivi du nom de la fonction.
|
||||
- Entre parenthèses on ajoute les paramètres qu'il faudra fournir
|
||||
- À la fin de la ligne on met `:` (encore et toujours)
|
||||
- On passe à la ligne suivante et on indente pour écrire les instructions.
|
||||
- Les paramètres fonctionnent comme des variables : on peut les utiliser dans la fonction avec leur nom.
|
||||
- On peut définir une valeur par défaut à un paramètre : il suffit d'écrire `parametre=valeur_par_defaut` lors de la déclaration. On peut alors omettre le paramètre, qui prendra automatiquement la valeur par défaut.
|
||||
- Deux fonctions ne peuvent pas avoir le même nom, sinon, la dernière a avoir été déclarée écrase la précédente.
|
||||
```
|
||||
|
||||
```admonish tip title='Bonnes pratiques'
|
||||
- On nomme les fonctions en `snake_case` en Python
|
||||
- Faites des fonctions courtes qui vont à l'essentiel (20 lignes est un bon maximum)
|
||||
- Choisissez bien les noms de vos fonctions et de vos paramètres pour qu'ils soient clairs et explicites
|
||||
- Vous pouvez documenter vos fonctions à l'aide d'une **docstring** : après l'en-tête de la fonction, avant le bloc d'instructions vous pouvez écrire une chaîne de caractères qui commence par 3 `"` ou `'`.
|
||||
Exemple:
|
||||
~~~python
|
||||
def ma_fonction(arg_1, arg2):
|
||||
"""Ceci est une docstring qui vient documenter ma fonction.
|
||||
Une docstring peut prendre plusieurs lignes.
|
||||
"""
|
||||
# Bloc d'instructions
|
||||
~~~
|
||||
```
|
||||
|
||||
### 2.3 - L'instruction `return`
|
||||
|
||||
```admonish travail
|
||||
1. Créez un nouveau fichier dans l'explorateur, nomme carre.py puis copiez la fonction ci-dessous :
|
||||
~~~python
|
||||
def aire_carre(cote):
|
||||
aire = cote * cote
|
||||
return aire
|
||||
~~~
|
||||
Que fait l'instruction `return` selon vous ? N'hésitez pas à expérimenter
|
||||
2. Donnez le code permettant d'affecter le résultat de la fonction à une variable pour ensuite l'afficher. Vous pourrez calculer l'aire d'un carré de côté 3m pour cet exemple.
|
||||
1. Expérimentez pour répondre aux questions suivantes. Donnez le code utilisé à chaque fois.
|
||||
1. Que retourne une fonction qui utilise l'instruction `return` sans préciser de valeur ?
|
||||
1. Que se passe-t-il si une instruction se trouve après l'instruction `return` dans votre fonction ?
|
||||
1. Que retourne une fonction qui n'a pas d'instruction `return` ?
|
||||
1. Nous voulons maintenant que notre fonction renvoie l'aire **et** le périmètre d'un carré. Pour cela, modifions la fonction comme suit.
|
||||
~~~python
|
||||
def carre(cote):
|
||||
aire = cote * cote
|
||||
perimetre = cote * 4
|
||||
return aire, perimetre
|
||||
~~~
|
||||
1. Affectez le résultat de la fonction à une variable. Que vaut-elle ?
|
||||
2. Appelez la fonction de la manière suivante : `aire_carre, perimetre_carre = carre(3)`. Que valent les variables `aire_carre` et `perimetre_carre` ? Que s'est-il passé selon vous ?
|
||||
1. Écrivez une fonction qui permet de diviser deux nombres. Cette fonction devra renvoyer la chaîne de caractères "Erreur : division par zéro impossible" si le deuxième nombre vaut zéro. Elle renverra le résultat dans tous les autres cas. Appelez la fonction dans les deux cas et affichez le résultat pour vérifier qu'elle fonctionne comme prévu.
|
||||
```
|
||||
|
||||
```admonish success title="A retenir"
|
||||
- L'instruction `return` permet de sortir immédiatement d'une fonction. Rien ne s'exécutera après le `return`
|
||||
- `return` permet de retourner un résultat, avec la syntaxe `return valeur`. Si aucune valeur n'est mentionnée, elle retournera `None`
|
||||
- Si `return` n'est pas mentionnée, la fonction s'exécute jusqu'au bout et sortira à la fin du bloc d'instructions en retournant `None`
|
||||
- On peut retourner plusieurs valeurs en les séparant par une virgule.
|
||||
- Ces valeurs peuvent être affectées à une seule variable sous forme d'un **tuple** (nous en parlerons au prochain TP)
|
||||
- Chaque valeur peut être affectée à une variable différente avec la syntaxe `variable_1, variable_2 ... = nom_de_la_fonction(...)`.
|
||||
```
|
||||
|
||||
### 2.4 - Mise en pratique
|
||||
|
||||
Nous allons mettre en pratique ce que nous avons vu jusqu'à maintenant dans un script un peu plus conséquent.
|
||||
|
||||
L'objectif est de créer un mini jeu dans lequel vous pourrez jouer à la roulette. Les règles seront évidemment simplifiées.
|
||||
|
||||
- Le joueur mise sur un nombre (entier) entre 0 et 49, et annonce une mise en jetons (par exemple : 20 jetons).
|
||||
- La croupière lance la roulette, et celle-ci déterminera le numéro gagnant. Les numéros impairs ont une couleur rouge, les numéros pairs sont noirs.
|
||||
- Si le joueur a misé sur le numéro gagnant, il remporte 3 fois sa mise
|
||||
- Si le joueur a misé sur un nombre de même couleur (donc de même parité que le numéro gagnant), il remporte 0,5 fois sa mise (arrondi à l'entier supérieur, car les jetons sont toujours entiers)
|
||||
- Sinon, le joueur perd sa mise. Notons qu'il la garde dans les deux autres cas, en plus de ses gains.
|
||||
- Le joueur aura 100 jetons disponibles au début de la partie. Il ne peut miser qu'un nombre entier de jeton, et seulement des jetons qu'il possède.
|
||||
- Si le joueur tombe à zéro jetons, la partie est finie.
|
||||
- Sinon, il peut rejouer (mais n'est pas obligé).
|
||||
|
||||
Imprégnez-vous bien des règles du jeu.
|
||||
|
||||
|
||||
```admonish travail
|
||||
1. Créez un nouveau fichier appelé `roulette.py`.
|
||||
2. Copiez le contenu suivant dedans. Ce sera la structure du script, que vous complèterez à l'aide des questions suivantes.
|
||||
|
||||
Il y a de nombreux `#TODO` (parfois `"#TODO"`) qu'il faudra remplacer par le code adéquat.
|
||||
|
||||
L'instruction `pass` sert à ne rien faire tout en ayant un script valide qui pourra donc s'exécuter sans erreur pour que vous puissiez avancer et tester votre code. Vérifiez que le code ci-dessous fonctionne sans erreur (il ne fera évidemment pas ce qui est demandé, ça c'est votre job !)
|
||||
|
||||
~~~python
|
||||
from random import randint
|
||||
#TODO
|
||||
|
||||
def miser(jetons_restants):
|
||||
#TODO
|
||||
return 7, 12
|
||||
|
||||
def choisir_nombre():
|
||||
nombre = -1
|
||||
while "#TODO condition" :
|
||||
nombre = "#TODO demander un nombre à l'utilisatrice"
|
||||
if "#TODO condition":
|
||||
print("Erreur : le nombre doit être compris entre 0 et 49")
|
||||
return nombre
|
||||
|
||||
#TODO fonction miser_jetons
|
||||
|
||||
def tourner_la_roulette():
|
||||
numero = 8 #TODO
|
||||
print(f"Le croupier tourne la roulette. Le numéro {numero} est le numéro gagnant !")
|
||||
return numero
|
||||
|
||||
def calculer_gains_couleur(mise):
|
||||
pass #TODO
|
||||
|
||||
def calculer_gains_numero(mise):
|
||||
pass #TODO
|
||||
|
||||
def continuer_de_jouer(jetons_restants):
|
||||
return #TODO Effacer cette ligne quand ce sera demandé
|
||||
if "#TODO condition":
|
||||
print("Vous êtes ruiné.e. C'est la fin de la partie.")
|
||||
#TODO Retourner une valeur
|
||||
else:
|
||||
#TODO Afficher les jetons restants (avec une phrase)
|
||||
rejouer = input("Souhaitez-vous continuer ? (o/n)")
|
||||
if rejouer == "o" or rejouer == "O":
|
||||
pass #TODO Retourner une valeur
|
||||
else:
|
||||
#TODO Annoncer qu'on quitte le jeu avec le nombre de jetons restants
|
||||
pass #TODO Retourner une valeur
|
||||
|
||||
jetons = 100
|
||||
continuer = True
|
||||
|
||||
while continuer:
|
||||
gains = 0
|
||||
numero_misé, mise = miser(jetons)
|
||||
|
||||
numero_gagnant = tourner_la_roulette()
|
||||
#TODO Écrire ici la condition principale, pour déterminer les gains
|
||||
|
||||
jetons += gains
|
||||
continuer = continuer_de_jouer(jetons)
|
||||
~~~
|
||||
|
||||
3. Expliquez les étapes du programme qui se déroulent dans la boucle à la fin du script, et quand est-ce qu'elle s'arrête.
|
||||
1. Complétez les fonctions suivantes à l'aide des règles du jeu :
|
||||
1. `calculer_gains_numero`
|
||||
1. `calculer_gains_couleur`. Comme nous voulons arrondir à l'entier supérieur, il faudra importer et utiliser la fonction `ceil` du module `math`.
|
||||
|
||||
Pour vérifier vos résultats, vous pouvez soit utiliser l'interpréteur en console, soit appeler les fonctions dans votre script et utiliser `print` pour afficher le résultat
|
||||
|
||||
2. Allez à la ligne `#TODO Écrire ici la condition principale, pour déterminer les gains`. Cette condition est celle qui permet de savoir si un joueur a gagné ou non.
|
||||
1. Écrivez la condition en utilisant les fonctions `calculer_gains_couleur` et `calculer_gains_numero`. N'oubliez pas le cas où le joueur perd.
|
||||
2. Ajoutez des `print` dans chaque branche pour annoncer les gains ou pertes.
|
||||
3. Testez les différents cas possibles en modifiant les valeurs retournées par la fonction `tourner_la_roulette`
|
||||
1. Maintenant que nous sommes sûrs que nos trois cas fonctionnent, nous allons pouvoir réellement tirer un nombre au hasard. Pour cela, nous avons déjà importé la fonction `randint` du module `random` dont voici la [documentation](https://docs.python.org/3.13/library/random.html#random.randint) :
|
||||
> random.**randint**(a, b)
|
||||
>
|
||||
> Return a random integer N such that a <= N <= b. Alias for randrange(a, b+1).
|
||||
|
||||
1. Expliquez brièvement ce que fait `randint`
|
||||
2. Modifiez la fonction `tourner_la_roulette` de façon à ce qu'elle retourne un nombre entre 0 et 49 tiré aléatoirement.
|
||||
|
||||
1. Le coeur du jeu semble maintenant fonctionner. Il ne reste plus qu'à permettre à la joueuse d'interagir avec le programme. Commençons par la mise.
|
||||
1. Complétez la fonction `choisir_nombre` de façon à ce que l'on demande à la joueuse un nombre tant que celui-ci n'est pas valide. Pour simplifier, considérons que personne ne s'amusera à entrer autre chose que des nombres (nous verrons plus tard dans l'année un moyen bien plus efficace de gérer les erreurs).
|
||||
2. Complétez la fonction `miser` pour qu'elle utilise notre fonction nouvellement complétée. Vérifiez que tout fonctionne comme prévu.
|
||||
3. Sur le même modèle que `choisir_nombre`, écrivez une fonction `miser_jetons` qui permettra à la joueuse de choisir un nombre de jetons à miser. Attention : il faudra vérifier qu'elle ne mise pas plus de jetons que ce qu'elle a. Vous aurez donc besoin d'un paramètre pour passer le nombre de jetons restants à votre fonction.
|
||||
4. Complétez la fonction `miser` pour qu'elle utilise notre nouvelle fonction. Vérifiez que tout fonctionne comme prévu.
|
||||
|
||||
1. Maintenant, il ne reste plus qu'à demander au joueur s'il souhaite continuer de jouer, et mettre fin à la partie s'il n'a plus de jetons. Dans la fonction `continuer_de_jouer`, retirez la première ligne, celle qui contient un `return`. Complétez le reste de la fonction en remplaçant les lignes contenant la mention `#TODO`. Testez votre programme de bout en bout.
|
||||
|
||||
1. Mettez le programme final dans votre compte rendu.
|
||||
```
|
||||
|
||||
# Annexes
|
||||
|
||||
## Un peu d'anglais
|
||||
|Français|Anglais|
|
||||
|-|-|
|
||||
|Appeler une fonction|Call a function|
|
||||
|Virgule|Comma|
|
||||
|Parenthèses|Brackets|
|
||||
|Crochets|Square brackets|
|
||||
|Accolades|Curly brackets|
|
||||
|
|
@ -6,141 +6,197 @@
|
|||
|
||||
- **Fonctions** : Création de fonctions
|
||||
- **Refactorisation** : réorganiser le code existant
|
||||
- **Modules** : Import de modules externes
|
||||
- **Modules** : Répartir le code dans différents fichiers
|
||||
|
||||
### Objectif technique
|
||||
### Objectifs techniques
|
||||
|
||||
Créer un menu interactif pour que l'utilisateurice puisse choisir son option
|
||||
|
||||
```
|
||||
================================================
|
||||
CIEL - Générateur de mots de passe
|
||||
================================================
|
||||
Quel type de mot de passe souhaitez-vous créer ?
|
||||
1 - Mot de passe avec configuration par défaut
|
||||
2 - Mot de passe avec configuration personnalisée
|
||||
3 - Phrase de passe avec configuration par défaut
|
||||
4 - Phrase de passe avec configuration personnalisée
|
||||
0 - Quitter
|
||||
Saisissez votre choix : 1
|
||||
Mot de passe par défaut
|
||||
```
|
||||
- Générer un mot de passe
|
||||
- Réorganiser le code en créant un module pour générer les mots de passe
|
||||
|
||||
## Étapes
|
||||
|
||||
### 1 - Préparation
|
||||
### 1 - Fonction `afficher_menu`
|
||||
|
||||
**Objectif :** Préparer votre fichier de script et commencer à travailler avec Thonny
|
||||
**Objectif :** Créer une fonction `afficher_menu` qui affiche le menu.
|
||||
|
||||
```admonish travail
|
||||
- Créer un fichier `main.py` dans votre répertoire de travail
|
||||
- Créer une fonction `afficher_menu` qui ne prend aucun paramètre.
|
||||
- Extraire dans cette fonction tout le code permettant d'**afficher** votre menu
|
||||
- Remplacer le code d'affichage par un appel à votre nouvelle fonction
|
||||
```
|
||||
|
||||
### 2 - Affichage du titre et du menu
|
||||
|
||||
**Objectif :** Afficher le titre et toutes les options du menu
|
||||
|
||||
```admonish tip title="A utiliser"
|
||||
- La fonction `print`
|
||||
```admonish warning title="Attention"
|
||||
On garde la variable `choix` et le `input` dans le corps du script. Cette ligne ne change pas de place.
|
||||
```
|
||||
|
||||
**Résultat attendu :**
|
||||
```
|
||||
================================================
|
||||
CIEL - Générateur de mots de passe
|
||||
================================================
|
||||
Quel type de mot de passe souhaitez-vous créer ?
|
||||
1 - Mot de passe avec configuration par défaut
|
||||
2 - Mot de passe avec configuration personnalisée
|
||||
3 - Phrase de passe avec configuration par défaut
|
||||
4 - Phrase de passe avec configuration personnalisée
|
||||
0 - Quitter
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le code de la fonction
|
||||
1. Où doit être déclarée la fonction ?
|
||||
1. Comment tester que la fonction marche ?
|
||||
```
|
||||
|
||||
### 2 - Fonction `choix_generateur`
|
||||
|
||||
**Objectif :** Créer une fonction qui reçoit le choix de l'utilisateur et le traite
|
||||
|
||||
```admonish travail
|
||||
- Utilisez du code pour afficher exactement le texte ci-dessus
|
||||
- Créer une fonction `choix_generateur` qui prend en paramètre le choix de l'utilisateur.
|
||||
~~~python
|
||||
def choix_utilisateur(choix):
|
||||
# Ecrire le code ici
|
||||
~~~
|
||||
- Extraire dans cette fonction tout le code permettant de gérer vos choix et afficher la ligne correspondante
|
||||
- Remplacer votre ancien code par un appel à la nouvelle fonction. N'oubliez pas de passer votre variable en paramètre
|
||||
```
|
||||
|
||||
### 3 - Demander le choix à l'utilisateur
|
||||
```admonish warning title="Attention"
|
||||
Si vous avez utilisé `break` dans votre structure conditionnelle, cela ne fonctionnera plus : il se trouve dans une sous-fonction, et donc il n'est plus directement dans la boucle.
|
||||
|
||||
**Objectif :** Afficher "Saisissez votre choix : " et récupérer la réponse de l'utilisateur
|
||||
|
||||
```admonish tip title="A utiliser"
|
||||
- La fonction `input`
|
||||
Il faudra donc gérer la pause avec une condition sur `choix`.
|
||||
```
|
||||
|
||||
```admonish question
|
||||
1. Quel est le type de la donnée récupérée via `input`
|
||||
2. Comment allez-vous stocker cette donnée ? Quel type aura la variable ?
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le code de la fonction
|
||||
1. Donner le nouveau code de votre boucle principale
|
||||
1. Pourquoi passer la varaible choix en paramètre au lieu d'une variable globale ?
|
||||
1. Si je modifie choix dans ma fonction, qu'en est-il de la variable choix originale (celle à l'extérieur de la fonction) ?
|
||||
```
|
||||
|
||||
|
||||
### 4 - Gérer les choix valides
|
||||
### 3 - Fonction `generer_mdp`
|
||||
|
||||
**Objectif :** Utiliser des conditions pour gérer les choix de l'utilisateur (1, 2, 3, 4 et 0)
|
||||
**Objectif :** Créer une fonction pour générer un mot de passe (fixe pour le moment)
|
||||
|
||||
```admonish tip title="A utiliser"
|
||||
- `if`
|
||||
- `elif`
|
||||
- Opérateurs de comparaison
|
||||
```admonish travail
|
||||
1. Créer une fonction `generer_mdp` qui retourne simplement la chaîne de caractères `P@ssw0rd!`. Penser à utiliser l'instruction `return`
|
||||
1. Utiliser cette fonction dans le choix 1 pour afficher le mot de passe généré dans la console.
|
||||
```
|
||||
|
||||
**Résultat attendu :** Afficher le texte pour chacun des cas
|
||||
|
||||
|Choix|Texte à afficher|
|
||||
|-|-|
|
||||
|1|Mot de passe par défaut|
|
||||
|2|Mot de passe personnalisé|
|
||||
|3|Phrase de passe par défaut|
|
||||
|4|Phrase de passe personnalisée|
|
||||
|0|Vous quittez le programme|
|
||||
|
||||
### 5 - Gérer les choix invalides
|
||||
|
||||
**Objectif :** Traiter le cas où l'utilisateur saisit un choix non valide
|
||||
|
||||
```admonish tip title="A utiliser"
|
||||
- Ajouter un `else` pour capturer les autres cas
|
||||
- Utiliser une chaîne formatée
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le code de la nouvelle fonction créée
|
||||
1. Donner le code de `choix_generateur` après l'avoir modifiée
|
||||
1. Est-ce une bonne idée d'utiliser `P@ssw0rd!` comme vrai mot de passe pour un de vos comptes en ligne ? Pourquoi ?
|
||||
```
|
||||
|
||||
**Résultat attendu :** Afficher le texte `Erreur : l'option 6 n'existe pas` (si le choix de l'utilisateur est 6 par exemple)
|
||||
### 4 - Création d'un module `mdp`
|
||||
|
||||
```admonish question
|
||||
1. Que se passe-t-il lorsque l'utilisateurice saisit une lettre au lieu d'un chiffre lors du choix de l'option ? Pourquoi à votre avis ? Nous ignorerons cette possibilité pour le moment, et verrons plus tard dans l'année comment le gérer.
|
||||
**Objectif :** Créer un module `mdp` pour y mettre tout ce qui concerne la génération de mots de passe, et l'importer dans le code principal
|
||||
|
||||
```admonish travail
|
||||
1. Créer un nouveau fichier `mdp.py`
|
||||
1. Déplacer la fonction `generer_mdp` dans ce nouveau fichier
|
||||
1. Importer le module mdp dans le fichier principal
|
||||
1. Modifier l'appel à la fonction `generer_mdp` pour tenir compte de son déplacement dans un module
|
||||
1. Vérifier que tout fonctionne comme avant
|
||||
```
|
||||
|
||||
### 6 - Ajouter une boucle
|
||||
```admonish help title="Aide"
|
||||
- Pour importer le module `mdp` il faut utiliser l'instruction `import`
|
||||
- Pour utiliser la fonction `generer_mdp` du module `mdp`, il faut préciser le nom du module : `mdp.generer_mdp()`
|
||||
~~~python
|
||||
import mdp
|
||||
|
||||
**Objectif :** Le programme doit pouvoir être répété autant que l'utilisateur le veut.
|
||||
... # Code du script
|
||||
|
||||
```admonish tip title="Quelle boucle utiliser ?"
|
||||
- La boucle `for` s'utilise pour un nombre connu d'itérations
|
||||
- La boucle `while` s'utilise pour un nombre non défini à l'avance d'itérations
|
||||
mdp.generer_mdp()
|
||||
|
||||
... # Encore du code
|
||||
~~~
|
||||
```
|
||||
|
||||
```admonish warning title="Gestion de la pause"
|
||||
Si le choix de l'utilisateurice est différent de zéro (pour quitter), il faut avoir le temps de lire avant de réafficher le menu.
|
||||
|
||||
Pour cela on peut demander une entrée (avec `input`) à l'utilisateurice, mais ignorer sa saisie. On peut alors simplement lui proposer d'appuyer sur Entrée. Une fois la saisie effectuée, on pourra alors reboucler.
|
||||
```admonish warning title="Attention"
|
||||
Ne pas oublier de préciser le nom du module avec un point lorsqu'on appelle une fonction qui est dans un module externe (`mon_module.ma_fonction()`)
|
||||
```
|
||||
|
||||
```admonish question
|
||||
1. Quelle boucle sera la plus adaptée ? Pourquoi ?
|
||||
2. Comment éviter de déclencher la pause lorsque l'utilisateurice souhaite quitter le programme ?
|
||||
```admonish note title="Dans le compte rendu"
|
||||
- Mettre le code du nouveau module
|
||||
- Mettre la ligne modifiée pour appeler `generer_mdp` depuis le script principal
|
||||
- Quel est l'intérêt de créer des modules séparés pour certaines portions de code ?
|
||||
```
|
||||
|
||||
|
||||
### 5 - Modification de `generer_mdp` pour générer un vrai mot de passe
|
||||
|
||||
**Objectif :** Générer un mot de passe réellement aléatoire de taille fixe
|
||||
|
||||
```admonish travail
|
||||
1. Dans le module `mdp`, tout en haut du fichier, importer les modules `secrets` et `string` qui sont livrés avec Python
|
||||
1. En haut du fichier, après les imports, créer quatre **constantes** comme ci-dessous. Elles vont nous aider à définir l'ensemble des caractères autorisés dans les mots de passe
|
||||
~~~python
|
||||
LETTRES = string.ascii_letters # Définit toutes les lettres autorisées
|
||||
CHIFFRES = string.digits # Définit tous les chiffres autorisés
|
||||
SPECIAL = string.punctuation # Définit les caractères spéciaux autorisés
|
||||
|
||||
ALPHABET = LETTRES + CHIFFRES + SPECIAL # Ensemble complet des caractères autorisés
|
||||
~~~
|
||||
1. Modifier la fonction `generer_mdp` pour générer un mot de passe de 14 caractères. Pour cela :
|
||||
1. Ajouter une boucle qui bouclera 14 fois, grâce à la fonction `range`
|
||||
2. Dans cette boucle, nous allons ajouter un nouveau caractère à la variable `password`. Ce caractère sera tiré aléatoirement dans la constante `ALPHABET`.
|
||||
|
||||
Pour ça, nous allons utiliser la fonction `choice` du module `secrets` :
|
||||
~~~python
|
||||
password += secrets.choice(ALPHABET)
|
||||
~~~
|
||||
3. A la fin, une fois sorti de la boucle, nous retournons la variable `password`
|
||||
1. Vérifier que votre fonction marche en essayant de générer un mot de passe (via l'option 1)
|
||||
```
|
||||
|
||||
```admonish tip title="Remarques"
|
||||
1. Les constantes en Python sont comme des variables. La différence est qu'on ne voudra jamais changer leur valeur. Mais rien ne permet de l'empêcher. Alors pour savoir qu'il s'agit d'une constante et qu'elle ne devrait pas être modifiée, on lui donne un nom en majuscules. Il s'agit d'une convention courante en programmation.
|
||||
1. Les constantes `string.ascii_letters`, `string.digits`, `string.punctuation` sont des chaînes de caractères avec l'ensemble des caractères de chaque catégorie. Elles sont définies dans le module string pour nous faire gagner du temps et éviter d'en oublier.
|
||||
1. Pour ajouter un caractère à une chaîne, il suffit d'utiliser `+`
|
||||
~~~python
|
||||
ma_chaine = ma_chaine + "c"
|
||||
~~~
|
||||
```
|
||||
|
||||
```admonish warning title="Attention"
|
||||
- Ne pas oublier d'initialiser la variable `password` **avant la boucle** avec une chaîne de caractères vide : `""`
|
||||
- Appeler l'instruction `return` **après être sorti de la boucle**
|
||||
```
|
||||
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le nouveau code du module `mdp` **complet**
|
||||
1. Aller voir la [documentation du module `random` de python](https://docs.python.org/3/library/random.html).
|
||||
1. Expliquer en quelques mots le rôle de la bibliothèque `random`
|
||||
1. Il y a un avertissement important sur la page, dans l'introduction. À la lecture de cet avertissement, expliquer en quelques mots pourquoi nous avons choisi la bibliothèque `secrets` plutôt que `random` pour générer un mot de passe **sécurisé**.
|
||||
```
|
||||
|
||||
### 6 - Réutiliser `generer_mdp` pour créer un mot de passe de taille personnalisable
|
||||
|
||||
**Objectif :** Rendre personnalisable la taille du mot de passe généré, et compléter l'option 2 du menu
|
||||
|
||||
```admonish travail
|
||||
1. Modifier la fonction `generer_mdp` pour qu'elle puisse prendre un paramètre `password_length`. Ce paramètre aura une **valeur par défaut** : 14
|
||||
1. Modifier la boucle pour qu'elle puisse faire autant d'itérations que `password_length` le nécessite.
|
||||
1. Vérifier que le code fonctionne toujours normalement sans autre modification
|
||||
1. Modifier le choix 2 du menu pour :
|
||||
1. Demander à l'utilisateurice de saisir une longueur de mot de passe peronnalisée (avec `input`)
|
||||
1. Utiliser la fonction `generer_mdp` pour afficher un mot de passe aléatoire de la longueur demandée par l'utilisateurice
|
||||
1. Vérifier que le choix 2 vous permette de générer des mots de passe de taille choisie.
|
||||
```
|
||||
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le code modifié de la fonction `generer_mdp`
|
||||
2. Donner le code modifié du choix 2 du menu
|
||||
3. Expliquer pourquoi votre choix 1 fonctionne toujours alors que vous ne passez aucun paramètre à la fonction `generer_mdp`
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Livrez le code final en plus du compte-rendu du TP
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Le programme se lance sans erreur
|
||||
- [ ] Le titre s'affiche correctement
|
||||
- [ ] Toutes les options s'affichent
|
||||
- [ ] La saisie utilisateur fonctionne
|
||||
- [ ] Chaque option affcihe le bon message
|
||||
- [ ] Un choix (nombre entier) invalide affiche une erreur claire
|
||||
- [ ] Le code est propre, les variables sont correctement nommées et avec des noms compréhensibles
|
||||
- [ ] La fonction `generer_mdp` est créée avec les bons paramètres
|
||||
- [ ] Le module `mdp` est créé et contient les bonnes fonctions
|
||||
- [ ] Le code principal utilise les fonctions du module `mdp`
|
||||
- [ ] Les mots de passe générés avec l'option 1 comportent 14 caractères et sont aléatoires
|
||||
- [ ] Les mots de passe générés avec l'option 2 sont de la taille choisie et aléatoires
|
||||
- [ ] Les fonctions ont des docstrings minimales (avec explication de leur fonctionnalité)
|
||||
- [ ] Le code est propre, les variables et fonctions sont correctement nommées et avec des noms compréhensibles et adaptés
|
||||
|
||||
### Critères d'évaluation
|
||||
|
||||
|
|
@ -150,29 +206,45 @@ Pour cela on peut demander une entrée (avec `input`) à l'utilisateurice, mais
|
|||
- Réponse aux questions dans le compte-rendu
|
||||
|
||||
## Pour aller plus loin
|
||||
### Bonus - Améliorations
|
||||
- Personnaliser le titre avec votre nom
|
||||
- Améliorer le texte des options et les messages
|
||||
- Amélioration de la présentation du menu
|
||||
|
||||
### Bonus difficile - Utiliser l'instruction `match`
|
||||
### Bonus facile - Ajout de docstrings
|
||||
|
||||
```admonish warning title='Attention'
|
||||
Cette question n'est à faire **que si le reste du TP est terminé**. Elle demande plus d'autonomie et est beaucoup moins guidée.
|
||||
Si vous n'êtes pas très à l'aise avec Python ou la programmation il vaut mieux se concentrer sur le reste et bien comprendre.
|
||||
**Objectif**: Documenter votre code à l'aide de docstrings complètes et formatées au format Numpy
|
||||
|
||||
Cette section n'est pas nécessaire à la bonne exécution du TP ni des séances suivantes. On peut terminer sans la faire.
|
||||
|
||||
**Faites une copie de votre code dans un nouveau fichier avant toute modification afin de pouvoir revenir en arrière au prochain TP si vous ne terminez pas cette question.**
|
||||
```admonish travail
|
||||
1. À l'aide de la section "Bonnes pratiques" du cours, ajoutez des docstrings aux fonctions de votre TP pour les documenter en respectant la syntaxe Numpy fournie
|
||||
```
|
||||
|
||||
**Objectif :** Utiliser la documentation Python pour remplacer les conditions du menu par la structure `match`.
|
||||
|
||||
```admonish tip title="A utiliser"
|
||||
- Utiliser la documentation officielle de Python pour comprendre la structure `match` : [Documentation](https://docs.python.org/3/tutorial/controlflow.html#match-statements)
|
||||
- Utiliser la structure match pour remplacer la suite de conditions
|
||||
### Bonus difficile - Ajout de contraintes
|
||||
|
||||
**Objectif** : Créer une fonction `generer_mdp_avec_contraintes` pour ajouter des contraintes sur le nombre de caractères spéciaux et de chiffres
|
||||
|
||||
```admonish travail
|
||||
1. Créer une nouvelle fonction `generer_mdp_avec_contraintes` dans le module `mdp`. Cette fonction appellera `generer_mdp` et retournera le mot de passe généré. Elle prendra trois paramètres :
|
||||
- `password_length` pour la longueur du mot de passe. Cette valeur sera passée à `generer_mdp` telle quelle et aura 14 en valeur par défaut.
|
||||
- `special` pour le nombre minimum de caractères spéciaux. Sa valeur par défaut sera de 1.
|
||||
- `digits` pour le nombre minimum de chiffres. Sa valeur par défaut sera de 1.
|
||||
2. Ajouter une boucle qui permettra de re-générer le mot de passe tant qu'il ne comportera pas au moins `special` caractères spéciaux et `digits` chiffres. Il faudra pour cela :
|
||||
- Compter les caractères spéciaux (et les chiffres) dans votre mot de passe
|
||||
- Vérifier ensuite que ce nombre soit supérieur au paramètre correspondant (`digits` ou `special`)
|
||||
- Arrêter la boucle si ces deux conditions sont réunies (donc la continuer tant que les deux conditions ne sont pas réunies)
|
||||
3. Remplacer la fonction `generer_mdp` dans l'option 2 du menu pour utiliser votre nouvelle fonction.
|
||||
4. Vérfiez que les mots de passe générés respectent la contrainte par défaut
|
||||
5. Sur le modèle de la longueur du mot de passe, demander à l'utilisateurice de choisir les contraintes voulues.
|
||||
6. Documenter votre/vos nouvelles fonctions avec une docstring complète.
|
||||
```
|
||||
|
||||
```admonish question
|
||||
- Comment gérer les cas non prévus dans le menu (ce que faisait le `else`) avec `match` ?
|
||||
```admonish help title="Aide"
|
||||
1. Pour compter les caractères spéciaux (ou les chiffres) dans votre mot de passe, vous pouvez
|
||||
- faire une boucle 'for' sur votre mot de passe
|
||||
- vérifier si le caractère se trouve dans votre constante `SPECIAL` avec la syntaxe `caractere in SPECIAL`
|
||||
- et incrémenter une variable à chaque fois que la condition précédente est à `True`
|
||||
|
||||
2. Vous pouvez extraire le comptage et la validation de la contrainte dans une sous-fonction pour rendre votre code plus lisible.
|
||||
```
|
||||
|
||||
```admonish note title="Dans le compte rendu"
|
||||
1. Donner le code de la fonction `generer_mdp_avec_contraintes` et des éventuelles sous-fonctions créées.
|
||||
2. Donner le code modifié du choix 2 du menu
|
||||
```
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
- [Cours - 2 - Structures de contrôle](./CIEL1/01-bases-python/cours/python-bases-2-structures-controle.md)
|
||||
- [Cours - 3 - Fonctions](./CIEL1/01-bases-python/cours/python-bases-3-fonctions.md)
|
||||
- [TP1 - Générateur de mots de passe - Menu interactif](./CIEL1/01-bases-python/tp/TP_MDP01_menu.md)
|
||||
- [TP2 - Fonctions](./CIEL1/01-bases-python/tp/02_fonctions.md)
|
||||
- [TP2 - Générateur de mots de passe - Fonctions et Modules](./CIEL1/01-bases-python/tp/TP_MDP02_fonctions.md)
|
||||
- [TD1 - Bases](./CIEL1/01-bases-python/td/td01-python.md)
|
||||
- [TD2 - Fonctions ](./CIEL1/01-bases-python/td/td02-fonctions.md)
|
||||
- [Annexe - Visual Studio Code](./CIEL1/01-bases-python/annexes/vscode.md)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue