learn.chetana.fr

Typing strict, Protocols et dataclasses

13 min de lectureEssentiel

Le contrat : mypy --strict

Le projet compile avec mypy --strict : toute fonction est typĂ©e, tout Any qui fuit fait Ă©chouer la CI. Ce choix transforme Python en langage Ă  contrats — les signatures deviennent la documentation, et le refactoring redevient sĂ»r.

async def match_line(line: StructuredLine, catalog: CatalogProvider) -> MatchResult: ...

Protocol : l'interface sans héritage

La rĂšgle du projet : composition > hĂ©ritage, jamais d'ABC. L'outil : typing.Protocol — le structural typing (duck typing vĂ©rifiĂ© statiquement) :

from typing import Protocol

class CatalogProvider(Protocol):
    async def search(self, query: str, limit: int) -> list[Variant]: ...
    async def get_by_sku(self, sku: str) -> Variant | None: ...

# AUCUNE classe n'hérite de CatalogProvider. Toute classe qui a
# ces méthodes EST un CatalogProvider aux yeux de mypy :
class LocalCatalogProvider:                    # pas de « (CatalogProvider) » !
    async def search(self, query: str, limit: int) -> list[Variant]: ...

Avantage dĂ©cisif dans un modular monolith : engine dĂ©clare le Protocol chez lui (ou dans shared), catalog fournit une implĂ©mentation sans dĂ©pendre du consommateur — zĂ©ro couplage d'import, la frontiĂšre du module 0 tient toute seule.

dataclass(frozen=True, slots=True) : la donnée immuable

Les objets-valeurs du projet sont des dataclasses gelées :

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class MatchResult:
    variant_id: str
    score: float
    method: str      # "exact" | "hybrid" | "deep"
  • frozen=True : immuable → partageable entre tĂąches async sans effroi ;
  • slots=True : pas de __dict__ → moins de mĂ©moire, et les fautes de frappe d'attributs explosent au lieu de crĂ©er un champ silencieux (le « fail loud » du projet).
🐍 À toi de jouer
đŸ§© Quiz1/3

Ce qui distingue Protocol d'une classe abstraite (ABC) :

🃏 Flashcards1/4