51 points par GN⁺ 2025-04-24 | 5 commentaires | Partager sur WhatsApp
  • 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

 
hackerpropoker 2025-04-29

Du point de vue du backend, j’ai constaté que les métaclasses rendaient le débogage plus difficile.

 
ilotoki0804 2025-04-28

for-else est souvent considéré comme un anti-pattern, car beaucoup estiment qu’il n’améliore ni la lisibilité ni la clarté, et notez que asyncio.Future est traité comme un détail d’implémentation interne d’asyncio.

 
dkmin 2025-04-26

Merci. Surtout le point 10, je l’applique tout de suite.

Ajout de règles de codage IA..

 
yangeok 2025-04-25

Merci pour cette astuce.

 
GN⁺ 2025-04-24
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.

    • Cet article est né de 14 petits tweets écrits un mois avant le lancement du blog.
    • En lançant le blog, j’ai décidé de réutiliser ces tweets comme premier billet.
    • C’est pourquoi le fil peut sembler un peu étrange.
    • Le lundi, j’essayais de trouver quelque chose d’utile, et le vendredi quelque chose d’un peu plus insolite.
    • Le titre aussi, c’est simplement une collection de 14 fonctionnalités de Python que j’ai trouvées intéressantes en l’utilisant.
    • Je n’ai passé qu’environ 5 secondes à trouver le titre.
  • Chaque fois que j’utilise Python, je crains que mon code donne l’impression de mal utiliser Python.

    • Je suis surpris par la profondeur de ce que j’ignorais sur Python, ainsi que par ses évolutions.
    • Go me donne l’assurance que mon code ne paraîtra pas dépassé dans quelques années.
    • Excellent article.
  • Python doit rester Python, et golang, Rust et Typescript doivent chacun garder leur propre philosophie et leur propre design.

    • Je code en 4 langages depuis 28 ans, et je n’aime pas l’évolution de Python.
    • Si Python est devenu populaire, ce n’est pas à cause de couches supplémentaires comme le type checking ou les annotations.
    • J’ai vu des choses similaires dans d’autres langages.
    • C’est une liste complète des fonctionnalités introduites récemment.
    • Il existe aussi une liste plus ancienne que les lecteurs pourraient trouver utile.
  • Le plus grand atout de Python, c’est qu’il donne l’impression d’être du pseudo-code exécutable.

    • Le langage n’interfère pas avec les instructions au niveau du domaine.
    • Plus on ajoute de fonctionnalités, moins il est séduisant.
    • La plupart des gens ne comprennent pas Python en profondeur.
  • Remarque sur l’évaluation du paragraphe 9.3 : en présence d’une chaîne vide, l’évaluation se fait différemment.

    • La clause if-else traite la chaîne vide comme une valeur valide, tandis que l’opérateur or la traite comme équivalente à None.
  • En tant que personne passée de Javascript/Typescript à Python, c’est une ressource utile.

    • Les surcharges de typage existent pour compenser une fonctionnalité malheureuse de Javascript, et je les considère comme de la dette technique.
    • Les arguments keyword-only et positional-only ont une syntaxe si concise que je m’inquiète pour la lisibilité.
    • Les annotations futures m’ont récemment beaucoup aidé.
    • Les protocoles ressemblent à ceux de Typescript, mais ne paraissent pas très pythoniques.
    • Les métaclasses sont des outils puissants capables de résoudre des problèmes spécifiques.
  • La plupart des fonctionnalités ne sont pas des fonctionnalités avancées.

    • J’évite les métaclasses, car elles peuvent entraîner des comportements complexes.
    • Les « propriétés proxy » ne sont pas une fonctionnalité.
  • La seule chose que je changerais dans la liste, c’est l’inclusion des conteneurs de collections.abc.

    • Plusieurs commentaires n’aimaient pas l’opérateur walrus, mais une fois que j’ai trouvé un bon cas d’usage, je l’ai utilisé avec efficacité.
    • Lorsqu’on utilise des motifs d’expressions régulières, le code devient bien plus propre.
  • J’ai pris plaisir à lire cet article.

    • La plupart des fonctionnalités relèvent du module typing.
    • Je n’étais pas certain de l’intérêt des génériques ou des protocoles.
    • Je me demande si le code Python moderne utilisé en production emploie des types partout.