Exercice 05 - Compréhension de scripts Python

Mise en situation

Pour comprendre un nouveau langage de programmation, on doit souvent regarder des exemples. Des codes qu'un collègue à fait et qui n'est pas toujours bien commenté s'il jugeait cela simple.

Mais, bien sûr, quand on commence rien n'est simple! À vous de jouer pour comprendre le fonctionnement des scripts!

Modalités

À faire (étapes)

Premier script à analyser

  1. Copier le script complet dans un fichier nommé fib.py
  2. Ouvrir le script dans VS Code
  3. Lire au complet le script à analyser
  4. Commenter chacune des lignes avec ce que vous pensez que la ligne fait
    Ex: # Boucle qui permet de...
  5. À quoi pensez vous que le script sert concrètement?

Code Python

def  fib(n):
    a = 0
    b = 1
    c = 0
    while c < n:
        t = b
        b = a + b
        a = t
        c = c + 1
    return a

if __name__ == "__main__":
    position = int(input("Enter the position you seek: "))
    rep = fib(position)
    print("The value at position (" + str(position) + ") is: " + str(rep))

Deuxième script à analyser

Cet exercice couvre les concepts suivants :

  1. Importation de modules (random)
  2. Définition de fonction
  3. Variables et types de données (int, string)
  4. Génération de nombres aléatoires
  5. Boucles (while)
  6. Conditions (if, elif, else)
  7. Conversion de types (int())
  8. Entrées utilisateur (input())
  9. Affichage (print())
  10. Opérateurs de comparaison
  11. F-strings pour le formatage de chaînes

Pour réaliser cet exercice :

Code Python

import random

def deviner_nombre():
    # Générer un nombre aléatoire entre 1 et 100
    nombre_secret = random.randint(1, 100)
    tentatives = 0
    max_tentatives = 7

    print("Bienvenue dans le jeu de devinette !")
    print(f"Devinez un nombre entre 1 et 100. Vous avez {max_tentatives} tentatives.")

    while tentatives < max_tentatives:
        # Demander à l'utilisateur de deviner
        essai = input("Entrez votre guess : ")

        # Vérifier si l'entrée est un nombre valide
        if not essai.isdigit():
            print("Veuillez entrer un nombre valide.")
            continue

        essai = int(essai)
        tentatives += 1

        # Vérifier si le guess est correct
        if essai == nombre_secret:
            print(f"Bravo ! Vous avez deviné le nombre en {tentatives} tentatives.")
            return
        elif essai < nombre_secret:
            print("Le nombre est plus grand.")
        else:
            print("Le nombre est plus petit.")

        # Afficher le nombre de tentatives restantes
        restantes = max_tentatives - tentatives
        print(f"Il vous reste {restantes} tentative(s).")

    print(f"Désolé, vous avez épuisé vos {max_tentatives} tentatives. Le nombre était {nombre_secret}.")

if __name__ == "__main__":
    # Lancer le jeu
    deviner_nombre()

Troisième script à corriger (10 erreurs)

Mise en situation

Tu reçois un petit utilitaire censé vérifier rapidement si une adresse IPv4 est valide et si elle appartient à un espace privé. Problème : le script contient 10 erreurs. À toi de les repérer et de les corriger.

Concepts couverts

À faire (étapes)

  1. Copier le script ci-dessous dans un fichier nommé ip_checker.py.
  2. Ouvrir dans VS Code.
  3. Exécuter et corriger les erreurs une à une (l’interpréteur s’arrête à la première erreur).
  4. Pour chaque correction, ajouter un commentaire expliquant le problème.
  5. Quand le programme tourne, tester avec quelques adresses (ex.: 192.168.1.10, 10.0.0.5, 172.20.3.4, 256.1.1.1, abc.def.ghi.jkl).

Code Python

# ip_checker.py

import random

def valider_ipv4(adresse)   # 1) <- erreur
    octets = adresse.split('.')
    if len(octets) != 5:    # 2) <- erreur
        return False

    for i in range(1, len(octets)):  # 3) <- erreur
        octet = octets[i]
        if octet == "":
            print("Octet vide détecté")
        if int(octet) < 0 or int(octet) > "255":  # 4) <- erreur
            return False
    return True

def est_prive(ip):
    o = ip.split('.')
    if int(o[0]) == 10:
        return True
    elif int(o[0]) == 172 and 16 <= int(o[1]) <= 31:
        return True
    elif o[0] == 192 and o[1] == 168:  # 5) <- erreur
        return True
    else:
        return False

def main():
    adresse = input("Entrez une adresse IPv4: ")
    if not valider_ip(adresse):      # 6) <- erreur
        print("Adresse IPv4 invalide")
    else:
        if est_prive(adress):        # 7) <- erreur
            print("Adresse privée")
        else:
            print(f"Adresse publique: {adresse")  # 8) <- erreur

    tentative = random.randint(100, 1)  # 9) <- erreur
    print("Nombre aléatoire: " + tentative)  # 10) <- erreur

if __name__ == "__main__":
    main()

(Optionnel) Améliorations “MODE EXPERT”

Solution

  1. Deux-points manquant après la définition de fonction
    Ligne fautive :

    def valider_ipv4(adresse)

    Problème : SyntaxError — en Python, un bloc de fonction doit se terminer par :.
    Correction :

    def valider_ipv4(adresse):
  2. Mauvaise longueur d’adresse IPv4
    Ligne fautive :

    if len(octets) != 5:

    Problème : Une IPv4 doit avoir 4 octets, pas 5. C’est une erreur logique.
    Correction :

    if len(octets) != 4:
       return False
  3. Boucle qui saute le premier octet (off-by-one)
    Ligne fautive :

    for i in range(1, len(octets)):

    Problème : En partant à 1, on ignore l’octet d’indice 0.
    Correction (par indices) :

    for i in range(0, len(octets)):

    ou, plus Pythonique :

    for octet in octets:
  4. Comparaison entre int et str
    Ligne fautive :

    if int(octet) < 0 or int(octet) > "255":

    Problème : "255" est une chaîne. Comparer int à str lève TypeError.
    Correction :

    if int(octet) < 0 or int(octet) > 255:

    Bonus robustesse : vérifier que octet ne contient que des chiffres avant le int(octet) :

    if not octet.isdigit(): return False
  5. Comparaison de chaînes avec des entiers dans est_prive
    Ligne fautive :

    elif o[0] == 192 and o[1] == 168:

    Problème : o[0] et o[1] sont des chaînes. Comparées à des entiers, l’expression est toujours fausse → erreur logique.
    Correction (convertir avant) :

    elif int(o[0]) == 192 and int(o[1]) == 168:
       return True
  6. Appel d’une fonction qui n’existe pas (valider_ip vs valider_ipv4)
    Ligne fautive :

    if not valider_ip(adresse):

    Problème : NameError — faute de frappe dans le nom de fonction.
    Correction :

    if not valider_ipv4(adresse):
  7. Variable mal orthographiée (adress vs adresse)
    Ligne fautive :

    if est_prive(adress):

    Problème : NameError — variable inexistante.
    Correction :

    if est_prive(adresse):
  8. F-string mal fermée (parenthèse/accolade manquante)
    Ligne fautive :

    print(f"Adresse publique: {adresse")

    Problème : SyntaxError — il manque la } (et la parenthèse de print se ferme trop tôt).
    Correction :

    print(f"Adresse publique: {adresse}")
  9. Bornes inversées dans random.randint
    Ligne fautive :

    tentative = random.randint(100, 1)

    Problème : ValueError — pour randint(a, b), on doit avoir a <= b.
    Correction :

    tentative = random.randint(1, 100)
  10. Concaténation str + int
    Ligne fautive :

print("Nombre aléatoire: " + tentative)

Problème : TypeError — on ne peut pas concaténer une chaîne et un entier.
Correction (deux options) :

print("Nombre aléatoire: " + str(tentative))
# ou
print(f"Nombre aléatoire: {tentative}")