🐍
Senior 25 questions Python

Questions Python Senior

25 questions avancees pour les entretiens Python senior. Metaclasses, descripteurs, concurrence, optimisation et architecture.

1. Expliquez les decorateurs avances et les metaclasses en Python.

Les decorateurs sont des fonctions qui modifient le comportement d'autres fonctions ou classes. Un decorateur recoit une fonction et retourne une nouvelle fonction (ou la meme modifiee). Les decorateurs avec arguments necessitent une triple imbrication : la factory retourne le decorateur qui retourne le wrapper. functools.wraps preserve les metadata de la fonction originale. Les decorateurs de classe modifient ou enrichissent des classes entieres. Les metaclasses controlent la creation des classes (la classe d'une classe). type est la metaclasse par defaut. Definir une metaclasse avec class Meta(type) et surcharger new ou init. Cas d'utilisation : validation de schema, enregistrement automatique, API frameworks (Django models). ABCMeta pour les classes abstraites. En general, preferer les decorateurs aux metaclasses (plus simples).

2. Comment fonctionne le GIL et comment contourner ses limitations ?

Le GIL (Global Interpreter Lock) est un mutex dans CPython qui empeche l'execution simultanee de bytecode Python par plusieurs threads. Consequence : le multithreading Python ne parallelise pas les taches CPU-bound. Le GIL est libere pendant les operations I/O, ce qui rend le threading utile pour les taches I/O-bound (requetes HTTP, acces fichier). Solutions pour le CPU-bound : multiprocessing (processus separes, chacun avec son propre GIL), concurrent.futures.ProcessPoolExecutor (API simplifiee), extensions C/Cython (liberent le GIL pendant le calcul), numpy/pandas (operations vectorisees en C). Python 3.13+ introduit le mode free-threaded (sans GIL, optionnel). asyncio pour le I/O-bound concurrent dans un seul thread.

3. Expliquez les generateurs, les coroutines et async/await.

Les generateurs (yield) produisent des valeurs paresseusement. Ils implementent le protocole iterateur et conservent leur etat entre les appels next(). Les generator expressions (x for x in range(n)) sont des generateurs inline. Les coroutines (async def) sont des fonctions qui peuvent etre suspendues avec await. asyncio gere la boucle evenementielle. await suspend la coroutine et rend le controle a la boucle qui peut executer d'autres coroutines. asyncio.gather() execute plusieurs coroutines en parallele. Les async generators (async def avec yield) combinent les deux concepts. Les context managers asynchrones (async with) pour les ressources asynchrones. La difference clef : les generateurs sont pull-based (on demande la valeur), les coroutines sont push-based (elles attendent des evenements).

4. Comment structurer un projet Python de maniere professionnelle ?

Structure recommandee : src layout (src/monpackage/) pour eviter les imports accidentels depuis le repertoire racine. Fichiers essentiels : pyproject.toml (metadata, dependances, configuration des outils), README.md, LICENSE. Gestion des dependances : Poetry ou uv pour le lockfile reproductible. Tests : dossier tests/ avec pytest, conftest.py pour les fixtures partagees. Linting : ruff (remplace flake8 + isort + black, ultra rapide). Type checking : mypy ou pyright avec des annotations de type. Pre-commit hooks : ruff, mypy, tests rapides. CI/CD : GitHub Actions avec matrix testing (Python 3.10, 3.11, 3.12). Documentation : docstrings Google/NumPy style, Sphinx ou MkDocs pour la generation. Logging : module logging avec configuration structuree (pas de print).

5. Quels sont les patterns de concurrence en Python ?

Threading (concurrent.futures.ThreadPoolExecutor) : pour les taches I/O-bound (appels API, lecture de fichiers). Partage de memoire, mais limite par le GIL. Multiprocessing (ProcessPoolExecutor) : pour les taches CPU-bound. Processus separes, pas de GIL, mais cout de communication inter-processus (serialisation). asyncio : pour le I/O-bound concurrent dans un seul thread, tres performant pour les milliers de connexions simultanees (serveurs web, scrapers). Patterns : producer-consumer avec asyncio.Queue, fan-out/fan-in, semaphore pour limiter la concurrence. Trio : alternative a asyncio avec une conception plus sure (structured concurrency). Choix : asyncio pour les serveurs et le networking, threads pour le I/O simple, multiprocessing pour le calcul numerique.

6. Expliquez les descripteurs et le protocole de descripteur en Python.

Les descripteurs sont des objets qui definissent get, set, ou delete. Ils controlent l'acces aux attributs d'une classe. Les data descriptors (avec set ou delete) ont priorite sur le dict de l'instance. Les non-data descriptors (seulement get) ont une priorite plus basse. Les proprietes (@property) sont implementees comme des descripteurs. Les methodes sont des non-data descriptors (self est lie via get). Les classmethod et staticmethod sont aussi des descriptors. Cas d'utilisation : validation d'attributs, lazy loading, logging d'acces, computed attributes, ORMs (champs de modeles Django/SQLAlchemy). Le protocole de descripteur est le mecanisme fondamental derriere de nombreuses fonctionnalites de Python : properties, methods, classmethod, staticmethod, slots.

7. Comment optimiser les performances en Python ?

Strategies par ordre de priorite : 1) Algorithme : choisir la bonne structure de donnees (dict O(1) vs list O(n) pour les lookups). 2) Built-ins : utiliser les fonctions C natives (sum, min, max, sorted, collections.Counter). 3) Comprehensions : plus rapides que les boucles for equivalentes. 4) Profilage : cProfile pour le CPU, memory_profiler pour la memoire, py-spy pour le profilage sans overhead. 5) Caching : functools.lru_cache ou functools.cache pour la memoization. 6) NumPy/Pandas : operations vectorisees pour les donnees numeriques. 7) Cython/Numba : compilation en C pour les boucles critiques. 8) PyPy : interpreteur JIT alternatif (acceleration 2-10x sans changer le code). Eviter les micro-optimisations avant de profiler.

8. Qu'est-ce que le typing avance en Python ?

Depuis Python 3.5+, le type hinting ajoute des annotations de type. Types avances : Union (int | str depuis 3.10), Optional (T | None), Literal (valeurs specifiques), TypeVar (generiques), Protocol (structural typing, comme les interfaces sans heritage). Generic classes et fonctions avec TypeVar. TypedDict pour typer les dictionnaires avec des cles connues. ParamSpec et Concatenate pour typer les decorateurs preservant les signatures. dataclasses comme alternative typee aux NamedTuples. Overload pour les signatures multiples. Les outils mypy et pyright verifient les types statiquement. Les types sont ignores au runtime (sauf si utilisees avec des outils comme pydantic ou beartype pour la validation runtime).

9. Expliquez les context managers et le protocole with en Python.

Les context managers gerent les ressources avec le pattern acquire-use-release. Protocole : enter (acquisition, retourne la ressource) et exit (liberation, recoit les infos d'exception). Le bloc with garantit que exit est appele meme en cas d'exception. contextlib.contextmanager simplifie la creation avec un generateur (yield entre le setup et le teardown). Cas d'utilisation : fichiers (open), connexions DB, locks (threading.Lock), transactions, modifications temporaires (chdir, env vars), mesure de temps, suppression d'exceptions (contextlib.suppress). contextlib.ExitStack gere dynamiquement un nombre variable de context managers. Les async context managers (async with) avec aenter/aexit pour les ressources asynchrones.

10. Comment gerer les tests avances en Python ?

pytest est le standard. Fixtures : fonctions qui fournissent des donnees ou des ressources aux tests. Scopes : function (defaut), class, module, session. Parametrize : executer un test avec plusieurs jeux de donnees. Mocking : unittest.mock.patch pour remplacer des dependances (API, DB). monkeypatch (fixture pytest) pour modifier l'environnement. conftest.py : fixtures partagees entre les fichiers de test, auto-decouverts. Markers : @pytest.mark.slow pour categoriser les tests. Coverage : pytest-cov pour mesurer la couverture. Factories : factory_boy pour generer des objets de test. Property-based testing : Hypothesis genere automatiquement des cas de test. Integration tests : testcontainers pour lancer des conteneurs Docker (DB, Redis) pendant les tests. Organisation : tests/unit/ et tests/integration/ separes.

Besoin d'aide pour preparer vos entretiens ?

Decrivez votre profil pour des conseils de preparation personnalises.

Recevoir des conseils

Questions frequentes

Quel salaire attendre pour un senior Python en France ?
Un developpeur Python senior peut attendre entre 55 000 et 75 000 EUR brut annuel en province, et 65 000 a 90 000 EUR en Ile-de-France.
Quelles competences complementaires sont attendues ?
Architecture logicielle, Docker/Kubernetes, CI/CD, bases de donnees (SQL et NoSQL), et experience avec les frameworks (Django, FastAPI).

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.