- Présentation de 14 fonctionnalités avancées de Python, souvent méconnues, avec des exemples concrets
- Propose une explication approfondie du typage statique et de la conception structurelle autour de
typing, generics, protocols, context managers, etc.
- Inclut aussi le pattern matching structurel introduit à partir de Python 3.10, ainsi que des techniques d’optimisation des performances comme slots et les métaclasses
- Contient aussi des astuces pour écrire un code plus propre avec
f-string, cache, future, proxy, for-else, walrus, etc.
- Fournit pour chaque fonctionnalité des liens et ressources de référence pour aller plus loin, dans une présentation accessible même aux développeurs juniors
Résumé de 14 fonctionnalités avancées de Python
# Surcharge de typage
- Le décorateur
@overload permet de définir plusieurs signatures de type pour une même fonction
- Le vérificateur de types peut déduire précisément le type de retour selon les arguments transmis
Literal permet aussi de restreindre les valeurs de chaîne
- Il est également possible d’implémenter une signature de fonction exigeant soit
id, soit username
Literal peut servir d’alternative légère à un Enum pour renforcer la sûreté des types
# Arguments keyword-only / positional-only
- L’utilisation de
* permet de définir des arguments keyword-only (impossibles à passer en positionnel)
- L’utilisation de
/ permet de définir des arguments positional-only (impossibles à passer par mot-clé)
- Cela permet d’imposer clairement la manière d’utiliser les arguments lors de la conception d’une API
# Annotations différées (__future__)
- Les type hints étant normalement évalués immédiatement à l’exécution, cela peut poser des problèmes d’ordre de déclaration
from __future__ import annotations permet de différer le moment de l’évaluation
- Mais comme cela repose sur un traitement sous forme de chaînes, il faut rester prudent si l’on utilise les types au runtime
PEP 649 propose une amélioration avec une évaluation différée via l’attribut __annotations__
# Syntaxe des génériques (Generic)
- Depuis Python 3.12, une nouvelle syntaxe de définition des types génériques est prise en charge
- À la place de
TypeVar, on peut utiliser une forme plus intuitive comme class Foo[T, U: int]
- Les Variadic Generics ont également été introduits pour gérer des types variés
- La définition d’alias de type devient aussi plus concise, avec une forme comme
type Vector = list[float]
# Protocols
- Version orientée vérification de types du Duck Typing, ils permettent d’implémenter le sous-typage structurel
- Si une classe possède certaines méthodes, elle peut être considérée compatible sans héritage de type explicite
@runtime_checkable permet aussi d’étendre cela aux vérifications isinstance
# Context managers
- Ce sont des objets possédant les méthodes
__enter__ et __exit__, utilisés dans un bloc with
- Le décorateur
contextlib.contextmanager permet une implémentation simple basée sur une fonction
- Les opérations d’initialisation et de nettoyage sont effectuées avant et après
yield
# Pattern matching structurel
- La syntaxe
match-case permet de traiter intuitivement des structures de données complexes
- Elle prend en charge la déstructuration de tuples/listes, les motifs OR, les gardes (
if) et les jokers
- Comme le branchement se fait selon la structure des données, cela améliore la lisibilité et la maintenabilité
# Optimisation avec __slots__
- L’utilisation de slots fixes à la place de
__dict__ optimise la mémoire et les performances
__slots__ utilise un tuple contenant uniquement les noms d’attributs
- Cela empêche aussi l’ajout d’attributs inutiles à la classe
- Mais cela reste une micro-optimisation, à utiliser avec discernement
# Recueil d’astuces de style pour le code Python
- Syntaxe
for-else : le bloc else s’exécute si la boucle se termine sans break
- Opérateur walrus (
:=) : permet à la fois l’affectation et le test d’une variable
- Évaluation courte de
or : renvoie la première valeur vraie parmi plusieurs
- Chaînage des opérateurs de comparaison : permet de condenser le code, par exemple
0 < x < 10
# Formatage avancé avec les f-strings
- La syntaxe
f"{variable=}" permet des affichages utiles pour le débogage
- Nombreuses options de formatage pour les nombres (
:.2f, :+.2f, :,) et les dates (%Y-%m-%d)
- Elle permet aussi le centrage, le padding, l’affichage en pourcentage et d’autres usages du mini-langage de formatage
# Décorateurs de cache
@lru_cache et @cache permettent de mémoriser les résultats d’une fonction pour améliorer les performances
- C’est utile pour les fonctions récursives ou les calculs répétitifs
@cache a été introduit à partir de Python 3.9 et fournit par défaut un cache illimité
# Future en Python
- Fonctionnalité de gestion d’objets asynchrones comparable aux Promise en JavaScript
Future.set_result(), add_done_callback() et d’autres méthodes permettent de gérer les résultats de manière asynchrone
asyncio.Future() peut être utilisé avec await
- Avec
ThreadPoolExecutor, il est aussi possible de faire du traitement parallèle en arrière-plan
# Propriété proxy (Proxy Property)
- Permet à un attribut de classe de se comporter à la fois comme un attribut et comme une fonction
__get__, __call__, __repr__ permettent d’offrir ces deux comportements
- Dans la conception d’API, cela peut permettre de gérer de la même manière les valeurs par défaut et les appels paramétrés
- C’est surtout un exemple expérimental intéressant plutôt qu’une technique d’usage courant
# Métaclasses
- Ce sont des classes de classes qui servent à créer les classes elles-mêmes
- Elles permettent une logique méta comme la manipulation d’attributs de classe ou l’enregistrement automatique
- En pratique, elles peuvent le plus souvent être remplacées par des décorateurs
- Des frameworks comme Django, SQLAlchemy ou Pydantic utilisent néanmoins des métaclasses en interne
5 commentaires
Du point de vue du backend, j’ai constaté que les métaclasses rendaient le débogage plus difficile.
for-elseest souvent considéré comme un anti-pattern, car beaucoup estiment qu’il n’améliore ni la lisibilité ni la clarté, et notez queasyncio.Futureest traité comme un détail d’implémentation interne d’asyncio.Merci. Surtout le point 10, je l’applique tout de suite.
Ajout de règles de codage IA..
Merci pour cette astuce.
Commentaires sur Hacker News
Bonjour ! Je suis l’auteur original du blog ! J’ai été surpris de voir mon article arriver en première page de HN à 4 heures du matin.
Chaque fois que j’utilise Python, je crains que mon code donne l’impression de mal utiliser Python.
Python doit rester Python, et golang, Rust et Typescript doivent chacun garder leur propre philosophie et leur propre design.
Le plus grand atout de Python, c’est qu’il donne l’impression d’être du pseudo-code exécutable.
Remarque sur l’évaluation du paragraphe 9.3 : en présence d’une chaîne vide, l’évaluation se fait différemment.
En tant que personne passée de Javascript/Typescript à Python, c’est une ressource utile.
La plupart des fonctionnalités ne sont pas des fonctionnalités avancées.
La seule chose que je changerais dans la liste, c’est l’inclusion des conteneurs de collections.abc.
J’ai pris plaisir à lire cet article.