Python itertools : construire des pipelines d'itérateurs paresseux

Python itertools : construire des pipelines d'itérateurs paresseux

itertools est un module de la bibliothèque standard qui expose des briques d’itération combinables. Son intérêt n’est pas de remplacer une boucle for par une fonction au nom obscur, mais de manipuler des flux de données sans jamais les charger entièrement en mémoire. Chaque fonction retourne un itérateur paresseux : rien n’est calculé tant qu’on ne consomme pas le résultat. C’est ce qui permet de chaîner des transformations sur des millions d’éléments avec une empreinte mémoire constante. ...

29 mai 2026 · 8 min · Anthony
Python collections : Counter, defaultdict, deque et les autres

Python collections : Counter, defaultdict, deque et les autres

Le module collections est dans la bibliothèque standard Python depuis la version 2.4. Il expose des structures de données spécialisées qui résolvent des problèmes récurrents sans dépendance externe. Pourtant, beaucoup de développeurs continuent d’écrire des boucles de comptage, des initialisations conditionnelles de clés, ou des classes Point avec x, y, z alors que Counter, defaultdict et namedtuple font exactement cela, mieux et plus lisiblement. Voici les six structures que j’utilise régulièrement, avec les cas où elles changent vraiment quelque chose. ...

22 mai 2026 · 7 min · Anthony
Python operator : itemgetter, attrgetter et l'art de remplacer les lambdas

Python operator : itemgetter, attrgetter et l'art de remplacer les lambdas

La librairie operator fait partie de la bibliothèque standard de Python depuis toujours, et pourtant beaucoup de développeurs continuent d’écrire lambda x: x[0] ou lambda obj: obj.nom quand une fonction de operator ferait le même travail, en plus rapide et plus lisible. Comprendre ce que cette librairie offre, et comment elle est implémentée, change la façon dont on écrit du code fonctionnel en Python. Ce que contient operator operator expose des fonctions qui correspondent aux opérateurs du langage. operator.add(2, 3) est l’équivalent fonctionnel de 2 + 3, operator.lt(a, b) correspond à a < b. L’intérêt n’est pas de remplacer les opérateurs dans du code arithmétique ordinaire, ce serait absurde. L’intérêt est de pouvoir passer une opération comme argument à une fonction d’ordre supérieur (map, filter, sorted, reduce, functools.partial). ...

20 mai 2026 · 7 min · Anthony
Vues matérialisées vs cache Django pour les requêtes lentes

Vues matérialisées vs cache Django pour les requêtes lentes

Le réflexe face à un endpoint de reporting lent, c’est souvent le cache. Un @cache_page, un cache.set(), et le problème disparaît… jusqu’à la prochaine expiration. Cette approche a une limite structurelle que les vues matérialisées PostgreSQL résolvent à la racine. Le problème du cache sur les endpoints analytiques Le cache Django stocke le résultat d’une vue Python. La requête SQL coûteuse s’exécute quand même à chaque expiration du cache. Pour un rapport construit sur plusieurs JOINs et agrégations, ça signifie que le premier utilisateur après chaque cache miss attend plusieurs secondes. ...

13 mai 2026 · 4 min · Anthony
Optimiser les requêtes Django ORM avec defer(), only() et Prefetch()

Optimiser les requêtes Django ORM avec defer(), only() et Prefetch()

Par défaut, Django charge tous les champs d’un modèle à chaque requête. Sur une vue liste de 50 articles, cela signifie 50 fois le contenu complet, le résumé, les métadonnées, les champs de traduction, même si on n’affiche que le titre et la date. Quatre méthodes QuerySet Django permettent de contrôler précisément ce qui est chargé : defer(), only(), values_list() et Prefetch(). Résultat : 2 requêtes SQL au lieu de N+2, avec uniquement les colonnes nécessaires. ...

8 mai 2026 · 6 min · Anthony
Django select_for_update() : verrouillage de lignes et concurrence

Django select_for_update() : verrouillage de lignes et concurrence

Deux requêtes simultanées lisent le stock d’un produit, constatent qu’il en reste un, et toutes les deux valident la commande. Le stock passe à -1. Ce type de condition de course est difficile à reproduire en développement et dévastateur en production. select_for_update() est la réponse de Django : poser un verrou SQL au moment de la lecture pour garantir qu’aucune autre transaction ne peut modifier la ligne avant la fin de l’opération. ...

6 mai 2026 · 4 min · Anthony
Python __slots__ : optimiser la mémoire des instances, concrètement

Python __slots__ : optimiser la mémoire des instances, concrètement

Python crée par défaut un dictionnaire __dict__ pour chaque instance de classe. C’est flexible, pratique, mais coûteux en mémoire quand on instancie des milliers ou des millions d’objets. __slots__ est le mécanisme qui supprime ce dictionnaire et stocke les attributs dans une structure compacte. Gain typique : 40 à 60 % de mémoire en moins par instance. Ce que fait Python sans slots Sans rien déclarer, chaque instance porte son propre __dict__ : ...

6 mai 2026 · 4 min · Anthony
Renommer les champs Django ORM avec F() dans values()

Renommer les champs Django ORM avec F() dans values()

Quand on expose des données depuis un modèle Django vers une API ou un serializer, les noms de champs du modèle ne correspondent pas toujours à ce qu’on veut retourner. Le réflexe habituel : récupérer les instances, puis renommer en Python. Il existe une meilleure option : laisser la base de données faire le travail via F() dans values(). Le problème : les noms de champs s’imposent class Task(models.Model): name = models.CharField(...) created_at = models.DateTimeField(...) Si on veut retourner nom_tache au lieu de name, on récupère les données puis on renomme en Python, soit via une compréhension de dict, soit dans le serializer. Dans les deux cas, la transformation se fait après coup, en mémoire. ...

5 mai 2026 · 3 min · Anthony
Django Window Function vs GROUP BY : QuerySets chaînables

Django Window Function vs GROUP BY : QuerySets chaînables

Avec Django ORM, il existe deux façons d’ajouter une valeur calculée sur un ensemble de lignes : annotate() avec une agrégation classique (Max, Count, Sum…) ou annotate() avec une Window function. En surface, elles se ressemblent. En pratique, elles ont un comportement fondamentalement différent, et choisir la mauvaise peut bloquer toute la chaîne de filtrage. GROUP BY avec annotate() : des lignes qui s’écrasent Quand on combine values() et annotate() avec une agrégation, Django génère un GROUP BY en SQL. Le résultat : les lignes se regroupent, et on obtient une ligne par groupe. ...

4 mai 2026 · 4 min · Anthony
Django in_bulk() : optimiser les requêtes ORM et éviter le N+1

Django in_bulk() : optimiser les requêtes ORM et éviter le N+1

Quand on a une liste d’identifiants et qu’on veut récupérer les instances correspondantes, le réflexe habituel en Django c’est filter(pk__in=[...]). Ça marche, c’est une seule requête SQL. Mais in_bulk() est une optimisation ORM souvent ignorée : elle retourne un dictionnaire {id: instance} au lieu d’un QuerySet, ce qui change radicalement la façon d’accéder aux résultats. Là où filter() force un parcours O(n) pour retrouver un objet par son ID, in_bulk() donne un accès direct O(1). ...

4 mai 2026 · 4 min · Anthony

Newsletter

Reçois les nouveaux articles directement dans ta boite mail.

Pas de spam. Désabonnement en un clic.