🐍 Python : Trucs & astuces

Cette fiche rassemble des astuces pratiques et des techniques avancées pour améliorer votre code Python, optimiser vos scripts, et utiliser le langage de manière plus efficace au quotidien.

📑 Sommaire

🪄 L'opérateur "walrus" (:=)

Introduit avec Python 3.8, cet opérateur permet de réaliser une affectation dans une expression :

# Sans opérateur walrus
texte = input("Entrez un texte : ")
if len(texte) > 0:
    print(f"Vous avez saisi {len(texte)} caractères")

# Avec opérateur walrus
if (n := len(input("Entrez un texte : "))) > 0:
    print(f"Vous avez saisi {n} caractères")

Très utile dans les conditions, les boucles while et les compréhensions :

# Traiter des lignes jusqu'à une ligne vide
while (ligne := input()) != "":
    print(f"Traitement de : {ligne}")

# Filtrer des résultats avec une condition complexe
resultats = [resultat for x in data if (resultat := f(x)) > 0]

🚀 Compréhensions avancées

Les compréhensions permettent d'écrire du code concis et expressif :

# Compréhension de liste avec conditions
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
cubes_pairs = [x**3 for x in nombres if x % 2 == 0]
print(cubes_pairs)  # [8, 64, 216, 512, 1000]

# Compréhension imbriquée (matrice 3x3)
matrice = [[i*3+j+1 for j in range(3)] for i in range(3)]
print(matrice)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Compréhension de dictionnaire avec condition
carre_pairs = {x: x**2 for x in range(10) if x % 2 == 0}
print(carre_pairs)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# Compréhension d'ensemble avec transformation
voyelles = {lettre.upper() for lettre in "bonjour" if lettre in "aeiouy"}
print(voyelles)  # {'O', 'U'}

⚙️ Déballage multiple

Le déballage (unpacking) permet d'extraire des valeurs de séquences de manière élégante :

# Déballage simple
a, b, c = [1, 2, 3]
print(a, b, c)  # 1 2 3

# Ignorer certaines valeurs avec _
a, _, c = [1, 2, 3]
print(a, c)  # 1 3

# Déballage avec * (reste dans une liste)
premier, *milieu, dernier = [1, 2, 3, 4, 5]
print(premier)   # 1
print(milieu)    # [2, 3, 4]
print(dernier)   # 5

# Échanger des valeurs sans variable temporaire
a, b = 10, 20
a, b = b, a
print(a, b)  # 20 10

# Déballage de dictionnaire avec **
def afficher_infos(nom, age, ville):
    print(f"{nom}, {age} ans, habite à {ville}")

personne = {"nom": "Alice", "age": 30, "ville": "Paris"}
afficher_infos(**personne)  # Alice, 30 ans, habite à Paris

🪤 Gestion fine des exceptions

Capturez et gérez précisément les différents types d'erreurs :

# Capture multiple d'exceptions
try:
    valeur = int(input("Entrez un nombre : "))
    resultat = 10 / valeur
    print(f"Résultat : {resultat}")
except ValueError:
    print("Ceci n'est pas un nombre valide")
except ZeroDivisionError:
    print("Division par zéro impossible")
except Exception as e:
    print(f"Erreur inattendue : {e}")
else:
    print("Aucune erreur n'est survenue")
finally:
    print("Cette partie s'exécute toujours")

Grouper plusieurs exceptions :

try:
    # Code susceptible de générer des erreurs
    pass
except (ValueError, TypeError) as e:
    print(f"Erreur de type : {e}")

⏱️ Mesurer la performance

Plusieurs façons de mesurer le temps d'exécution de votre code :

# Méthode simple avec time
import time

start = time.time()
# ... votre code ...
end = time.time()
print(f"Durée : {end - start:.4f} secondes")

Utilisation de timeit pour des mesures précises :

import timeit

# Mesurer une ligne
temps = timeit.timeit('[x**2 for x in range(1000)]', number=10000)
print(f"Temps d'exécution : {temps:.4f} secondes")

# Mesurer une fonction
def ma_fonction():
    return sum(x**2 for x in range(1000))
    
temps = timeit.timeit(ma_fonction, number=10000)
print(f"Temps d'exécution : {temps:.4f} secondes")

Décorateur pour profiler une fonction :

def chronometre(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} a pris {end - start:.4f} secondes")
        return result
    return wrapper

@chronometre
def operation_couteuse():
    time.sleep(1)  # Simuler une opération longue
    return "Terminé"
    
operation_couteuse()  # Affiche : operation_couteuse a pris 1.0012 secondes
🎁 Bonus : Astuces avancées

Chaînes f (f-strings) avec formatage avancé

# Format avec la spécification de précision
nombre = 123.456789
print(f"{nombre:.2f}")  # 123.46

# Alignement et remplissage
for i in range(1, 11):
    print(f"{i:03d} - {i*i:4d} - {i*i*i:5d}")

# Formatage de dates
from datetime import datetime
maintenant = datetime.now()
print(f"{maintenant:%d/%m/%Y %H:%M}")  # Ex: 27/04/2025 14:30

# Débogage facile
x = 10
y = 20
print(f"{x=}, {y=}, {x+y=}")  # x=10, y=20, x+y=30

Collections spécialisées

from collections import Counter, defaultdict, namedtuple

# Counter pour compter les occurrences
texte = "abracadabra"
compteur = Counter(texte)
print(compteur)  # Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
print(compteur.most_common(2))  # [('a', 5), ('b', 2)]

# defaultdict pour des valeurs par défaut
fruits_par_couleur = defaultdict(list)
fruits_par_couleur["rouge"].append("pomme")  # Pas d'erreur même si la clé n'existe pas
fruits_par_couleur["rouge"].append("fraise")
print(fruits_par_couleur)  # defaultdict(, {'rouge': ['pomme', 'fraise']})

# namedtuple pour des tuples avec noms de champs
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)  # 10 20
print(p)  # Point(x=10, y=20)

Trucs pour le débogage

# Utiliser pdb, le débogueur intégré
import pdb

def fonction_complexe(x):
    y = x * 2
    pdb.set_trace()  # Le programme s'arrête ici et entre en mode débogage
    z = y * 3
    return z

# Utiliser `breakpoint()` (Python 3.7+) à la place de pdb.set_trace()
def autre_fonction(x):
    y = x * 2
    breakpoint()  # Équivalent à pdb.set_trace()
    z = y * 3
    return z
🏠 Retour au sommaire général