Chapitre 1 : Les bonnes pratiques.

Introduction:

Un code bien écrit n’est pas seulement fait pour fonctionner, il doit aussi être compris, relu et maintenu facilement. Les bonnes pratiques permettent de réduire les erreurs et de gagner du temps sur le long terme.

  • Documentation : facilite la compréhension globale du projet.
  • Commentaires : expliquent les choix techniques et les étapes clés.
  • Noms de variables explicites : rendent le code lisible et intuitif.

En appliquant ces principes, on obtient un code plus propre, maintenable et collaboratif.

1. Gestion des causes typiques de bugs:

Dans la pratique de la programmation, il faut savoir répondre aux causes typiques de bugs, notamment :

  1. problèmes liés au typage
  2. instruction conditionnelle non exhaustive
  3. débordements dans les tableaux
  4. comparaisons et calculs des nombres flottants
  5. mauvais nommage des variables

2. Exercice

A faire dans le cahier.

Donner un exemple court de code Python illustrant chacun des points ci-dessus.

3. Quelques bonnes pratiques:

Il existe quelques bonnes pratiques à avoir lorsque l'on écrit un programme Python :

4. Exemple:

def uniquement_positif(liste):
    for element in liste :        #Pour tous les éléments de la liste
        if element < 0 :    #On trouve un élément négatif. 
            return False
    return True            #On renvoie Vrai si on n'a pas trouvé de nombre négatif.

5. Exercice :

Écris une fonction divisible_par_7_et_par_5(x) qui prend en paramètre un entier x supérieur ou égal à 1 et retourne un entier.

Elle doit renvoyer :

  • 0 si x n’est divisible ni par 5 ni par 7.
  • 2 si x est divisible par 5 et par 7.
  • 1 si x est divisible par 5 ou 7, mais pas par les deux.

💡 Rappel sur l’opérateur modulo % :

  • a % b donne le reste de la division de a par b.
  • Exemples : 7 % 3 == 1 (car 7 = 2 × 3 + 1), 8 % 2 == 0 (car 8 est divisible par 2).

Ainsi, pour savoir si un nombre d est un diviseur de x, on peut tester : x % d == 0.

Ce code doit être commenté et en ayant fait attention d'avoir "de bonnes pratiques".

def divisible_par_7_et_par_5(x): ..................... if ................. : ............. if ................ : ............. return ................ # Exemple d'appel print(divisible_par_7_et_par_5(35)) # doit renvoyer 2

Tests :

# Doit retourner 0
print(divisible_par_7_et_par_5(1))

# Doit retourner 1 (divisible par 5 seulement)
print(divisible_par_7_et_par_5(5))

# Doit retourner 1 (divisible par 7 seulement)
print(divisible_par_7_et_par_5(7))

# Doit retourner 2 (divisible par 5 et 7)
print(divisible_par_7_et_par_5(35))

Affichage :

Console:



    
>>>

6. La documentation des fonctions (docstring)

A copier dans le cahier.

On peut ajouter une docstring (chaîne de documentation) juste après la définition d’une fonction, entre trois apostrophes '''. Elle sert à expliquer le rôle de la fonction.

On peut ensuite y accéder avec la fonction help.

def uniquement_negatif(liste):
    '''
    Renvoie True si tous les nombres de la liste sont négatifs, False sinon.
    '''
    for element in liste:
        if element >= 0:
            return False
    return True

7. Exercice :

Écris une fonction diviseur(x) qui prend en paramètre un entier x supérieur ou égal à 1 et qui retourne la liste de tous ses diviseurs.

Si le paramètre n’est pas un entier valide (par exemple un nombre négatif ou un autre type), la fonction doit retourner False.

Vous devez documenter et commenter votre code.

def diviseur(x): if ... : ... if ... : ... diviseurs = .... for i in range(1, ....): if ............. : diviseurs.append(......) return diviseurs # Exemple d'appel print(diviseur(12)) # [1, 2, 3, 4, 6, 12]

Tests :

# Doit retourner [1]
print(diviseur(1))

# Doit retourner [1, 2, 3, 6]
print(diviseur(6))

# Doit retourner [1, 2, 3, 4, 6, 12]
print(diviseur(12))

# Doit retourner False pour un nombre négatif
print(diviseur(-5))

# Doit retourner False pour une valeur non entière
print(diviseur(3.5))

Affichage :

Console:



    
>>>

8. L'assertion

A copier dans le cahier.

Une assertion est un test qui vérifie une condition pendant l’exécution. Si la condition est vraie, le programme continue ; sinon, il s’arrête avec une erreur.

En Python, on utilise assert :

x = -5
assert x < 0   # OK
assert x > 0   # Erreur !

Les assertions servent à sécuriser le code et à vérifier qu’une fonction fonctionne correctement.

9. Exercice :

Un nombre entier positif non nul est premier s’il comporte exactement deux diviseurs.

Écris une fonction decompo_facteurs_premiers(n) qui prend en paramètre un entier n supérieur ou égal à 1 et qui renvoie la liste des nombres correspondant à sa décomposition en facteurs premiers.

💡 Exemple : la décomposition en facteurs premiers de 30 est :

$$ 30 = 2 \times 15 = 2 \times 3 \times 5 $$

Consignes :

  • ⚠️ Inclure une assertion assert dans la fonction pour vérifier que n est bien un entier (integer).
  • ⚠️ Inclure une assertion assert dans la fonction pour vérifier que n est bien un entier supérieur ou égal à 1.
  • ⚠️ Écrire aussi des assertions à l’extérieur pour vérifier le bon fonctionnement de la fonction.
def decompo_facteurs_premiers(n): """ Retourne la liste des facteurs premiers de n. Précondition : n est un entier supérieur ou égal à 1. """ # Vérification du paramètre avec des assertions assert ........... assert .......... facteurs = [] diviseur = 2 while n > 1: if n % diviseur == .......: facteurs.append(........) n = n // ......... else: diviseur += ......... return facteurs # Assertions pour tester la fonction assert decompo_facteurs_premiers(30) == [2, 3, 5], "Test avec 30" assert decompo_facteurs_premiers(13) == [13], "Test avec un nombre premier" assert decompo_facteurs_premiers(12) == [2, 2, 3], "Test avec 12" print(decompo_facteurs_premiers(30))

Tests :

# Ces assertions doivent être vraies si la fonction est correcte
assert decompo_facteurs_premiers(30) == [2, 3, 5]
assert decompo_facteurs_premiers(13) == [13]
assert decompo_facteurs_premiers(12) == [2, 2, 3]

# Exemple d'affichage
print(decompo_facteurs_premiers(30))  # [2, 3, 5]

Affichage :

Console:



    
>>>

10. Exercice : (sujet 38 - 2025)

Ecrire une fonction qui prend en paramètre un tableau d'entiers non vide et qui renvoie la moyenne de ces entiers. La fonction est spécifiée ci-après et doit passer les assertions fournies.

def moyenne (tab):
    '''
    moyenne(list) -> float
    Entrée : un tableau non vide d'entiers
    Sortie : nombre de type float
    Correspondant à la moyenne des valeurs présentes dans le
    tableau
    '''
    ...


assert moyenne([1]) == 1
assert moyenne([1, 2, 3, 4, 5, 6, 7]) == 4
assert moyenne([1, 2]) == 1.5

11. Le typage des fonctions

A copier dans le cahier.

En Python, on peut préciser le type des paramètres et de la valeur de retour d’une fonction. Cela rend le code plus clair, même si ce n’est pas obligatoire.

def carre(nombre: int) -> int:
    return nombre * nombre

Ici, nombre: int indique que nombre est un entier et -> int que la fonction retourne un entier.

Ces annotations n’empêchent pas les erreurs à l’exécution mais aident à mieux lire et analyser le code.

12. Exercice : (sujet 2 - 2025)

Écris une fonction max_et_indice(tab) qui prend en paramètre une liste non vide tab d’entiers et retourne un tuple (valeur_max, indice) :

  • valeur_max : la plus grande valeur de la liste,
  • indice : l’indice de sa première apparition.

⚠️ L’utilisation de la fonction native max est interdite.

💡 Ajoute une documentation et des assertions pour vérifier que la liste n’est pas vide.

⭐ Exemples :

>>> max_et_indice([1, 5, 6, 9, 1, 2, 3, 7, 9, 8])
(9, 3)
>>> max_et_indice([-2])
(-2, 0)
>>> max_et_indice([-1, -1, 3, 3, 3])
(3, 2)
>>> max_et_indice([1, 1, 1, 1])
(1, 0)
def max_et_indice(tab: list) -> tuple: ... # Exemple d'appel print(max_et_indice([1, 5, 6, 9, 1, 2, 3, 7, 9, 8])) # (9, 3)

Tests :

Affichage :

Console:



    
>>>

13. Exercice : (sujet 20 - 2025)

Écris une fonction min_et_max(tab) qui prend en paramètre une liste tab non vide de nombres et retourne un dictionnaire avec deux clés :

  • 'min' : la plus petite valeur de la liste,
  • 'max' : la plus grande valeur de la liste.

⚠️ L’utilisation de min, max, sorted et sort est interdite : la solution doit parcourir la liste avec une boucle.

💡 Ajoute une documentation (docstring) et des assertions pour vérifier que la liste n’est pas vide.

⭐ Exemples :

>>> min_et_max([0, 1, 4, 2, -2, 9, 3, 1, 7, 1])
{'min': -2, 'max': 9}
>>> min_et_max([3])
{'min': 3, 'max': 3}
def min_et_max(tab: list) -> dict: ... # Exemple d'appel print(min_et_max([0, 1, 4, 2, -2, 9, 3, 1, 7, 1]))

Tests :

Affichage :

Console:



    
>>>

14. Exercice : (sujet 43 - 2025)

Écris une fonction couples_consecutifs(tab) qui prend en paramètre une liste non vide d’entiers et renvoie une liste de couples (a, b)b est le successeur de a (c’est-à-dire b = a + 1).

⚠️ La liste de départ tab peut contenir zéro, un ou plusieurs couples consécutifs.

💡 Ajoute une documentation et une assertion pour vérifier que la liste n’est pas vide.

⭐ Exemples :

>>> couples_consecutifs([1, 4, 3, 5])
[]
>>> couples_consecutifs([1, 4, 5, 3])
[(4, 5)]
>>> couples_consecutifs([1, 1, 2, 4])
[(1, 2)]
>>> couples_consecutifs([7, 1, 2, 5, 3, 4])
[(1, 2), (3, 4)]
>>> couples_consecutifs([5, 1, 2, 3, 8, -5, -4, 7])
[(1, 2), (2, 3), (-5, -4)]
def couples_consecutifs(tab: list) -> list: ... # Exemple d'appel print(couples_consecutifs([5, 1, 2, 3, 8, -5, -4, 7])) # [(1, 2), (2, 3), (-5, -4)]

Tests :

Affichage :

Console:



    
>>>