Chapitre 18
Chapitre 18 : QCM — 100 Questions à Choix Multiples
> **Évaluez vos connaissances** à travers 100 QCM couvrant l'intégralité du programme Modern Python Engineering.
Chapitre 18 — 100 Questions à Choix Multiples
Version : 1.0.0
Durée estimée : 90 minutes
Barème : 1 point par question, pas de points négatifs
Module 1 : Syntaxe et fondamentaux (Q01–Q15)
Q01. Quelle est la sortie de print(type(1/2)) ?
- A.
<class 'int'> - B.
<class 'float'> - C.
<class 'double'> - D.
<class 'number'>
Réponse : B — En Python 3, la division / retourne toujours un float.
Q02. Quelle est la différence entre is et == ?
- A.
iscompare les valeurs,==compare les identités - B.
iscompare les identités,==compare les valeurs - C. Les deux sont identiques
- D.
isest déprécié depuis Python 3.12
Réponse : B — is vérifie l'identité mémoire (id()), == vérifie l'égalité via __eq__.
Q03. Quel est le résultat de 3 * 'abc' + 'def' ?
- A.
abcabcdef - B.
abcabcabcdef - C.
TypeError - D.
abcabc def
Réponse : B — 3 * 'abc' → 'abcabcabc', puis + 'def' → 'abcabcabcdef'.
Q04. Quelle méthode de liste modifie la liste originale ?
- A.
sorted() - B.
list.sort() - C.
reversed() - D.
list.copy()
Réponse : B — list.sort() trie la liste en place. sorted() retourne une nouvelle liste.
Q05. Quelle est la sortie de print(list(range(5, 1, -1))) ?
- A.
[5, 4, 3, 2] - B.
[5, 4, 3, 2, 1] - C.
[4, 3, 2] - D.
[5, 4, 3]
Réponse : A — range(5, 1, -1) commence à 5, s'arrête avant 1, avec un pas de -1.
Q06. Quelle est la sortie de print(not True and False or True) ?
- A.
True - B.
False - C.
None - D.
SyntaxError
Réponse : A — L'ordre est : not True → False, False and False → False, False or True → True.
Q07. Que retourne any([[], [0], ['']]) ?
- A.
True - B.
False - C.
None - D.
TypeError
Réponse : A — [] est falsy, [0] est truthy (liste non-vide), [''] est truthy.
Q08. Quel est le résultat de {x: x**2 for x in range(5) if x % 2 == 0} ?
- A.
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16} - B.
{0: 0, 2: 4, 4: 16} - C.
{0: 0, 2: 4} - D.
{1: 1, 3: 9}
Réponse : B — range(5) = 0, 1, 2, 3, 4. Filtre x % 2 == 0 = 0, 2, 4.
Q09. Que fait *args dans une signature de fonction ?
- A. Déballe un dictionnaire
- B. Capture les arguments positionnels supplémentaires dans un tuple
- C. Capture les arguments nommés supplémentaires dans un dict
- D. Déclare un argument optionnel
Réponse : B — *args capture les arguments positionnels supplémentaires. **kwargs capture les nommés.
Q10. Quelle est la sortie de print("{{}}".format("x")) ?
- A.
x - B.
{} - C.
{{}} - D.
{x}
Réponse : B — Les doubles accolades {{}} s'échappent en accolades littérales.
Q11. Que retourne frozenset([1, 2, 2, 3]) ?
- A.
{1, 2, 3} - B.
frozenset({1, 2, 3}) - C.
{1, 2, 2, 3} - D.
[1, 2, 3]
Réponse : B — frozenset déduplique les éléments et retourne un set immuable.
Q12. Quel est le bon ordre de précédence des opérateurs (du plus fort au plus faible) ?
- A.
(),**,*,+,==,not,and,or - B.
(),**,*,+,==,and,or,not - C.
**,(),*,+,==,not,or,and - D.
(),**,==,*,+,and,or,not
Réponse : A — Parenthèses > Exponentiation > Multiplication > Addition > Comparaison > not > and > or.
Q13. Quelle est la sortie de print(0.1 + 0.2 == 0.3) ?
- A.
True - B.
False - C.
TypeError - D.
None
Réponse : B — Erreur de représentation flottante : 0.1 + 0.2 = 0.30000000000000004.
Q14. Que retourne bool([]) ?
- A.
True - B.
False - C.
None - D.
TypeError
Réponse : B — Les séquences vides ([], {}, (), "", set()) sont falsy.
Q15. Quelle est la sortie de print(1 if False else 2 if False else 3) ?
- A.
1 - B.
2 - C.
3 - D.
SyntaxError
Réponse : C — Expression ternaire droite-associative : 1 if False else (2 if False else 3).
Module 2 : Programmation orientée objet (Q16–Q25)
Q16. Que retourne isinstance(3.14, (int, float)) ?
- A.
True - B.
False - C.
TypeError - D.
None
Réponse : A — 3.14 est instance de float, qui est dans le tuple.
Q17. Quelle méthode doit-on implémenter pour utiliser len() sur un objet ?
- A.
__length__ - B.
__len__ - C.
__size__ - D.
__bool__
Réponse : B — __len__ est appelée par la fonction native len().
Q18. Que permet le paramètre slots=True dans un @dataclass (Python 3.10+) ?
- A. Déclarer des champs optionnels
- B. Générer automatiquement
__slots__pour économiser la mémoire - C. Figer l'instance (empêcher les mutations)
- D. Activer l'héritage multiple
Réponse : B — slots=True génère __slots__, réduisant la mémoire par instance.
Q19. Quelle est la différence entre @staticmethod et @classmethod ?
- A. Aucune, ce sont des synonymes
- B.
@classmethodreçoit la classe comme premier argument, pas@staticmethod - C.
@staticmethodpeut modifier l'état de la classe - D.
@classmethodne peut être appelé que sur des instances
Réponse : B — @classmethod reçoit cls, @staticmethod ne reçoit rien d'implicite.
Q20. Que retourne type(type) ?
- A.
<class 'type'> - B.
<class 'object'> - C.
<class 'function'> - D.
NoneType
Réponse : A — type est une métaclasse, sa métaclasse est elle-même.
Q21. Quel protocole permet d'utiliser async for sur un objet ?
- A.
__iter__/__next__ - B.
__aiter__/__anext__ - C.
__await__ - D.
__enter__/__exit__
Réponse : B — Le protocole asynchrone d'itération utilise __aiter__ et __anext__.
Q22. Que fait l'héritage multiple si deux classes parentes définissent la même méthode ?
- A. Python lève une exception
- B. La première classe dans le MRO gagne
- C. La dernière classe dans le MRO gagne
- D. Les deux méthodes sont fusionnées
Réponse : B — Le MRO (Method Resolution Order) donne priorité à la première classe listée.
Q23. Quelle est la sortie de print(type(1).__mro__) ?
- A.
(<class 'int'>, <class 'object'>) - B.
(<class 'object'>, <class 'int'>) - C.
(<class 'int'>,) - D.
(<class 'int'>, <class 'float'>, <class 'object'>)
Réponse : A — L'ordre de résolution des méthodes pour int est int → object.
Q24. Quelle fonction retourne toutes les méthodes d'un objet ?
- A.
vars() - B.
dir() - C.
help() - D.
locals()
Réponse : B — dir() retourne la liste des attributs et méthodes d'un objet.
Q25. Quel décorateur transforme une méthode en propriété en lecture seule ?
- A.
@classmethod - B.
@property - C.
@staticmethod - D.
@abstractmethod
Réponse : B — @property permet d'accéder à une méthode comme un attribut.
Module 3 : Typage statique (Q26–Q32)
Q26. Quel est le type de retour de def func(a: int) -> str: ... si la fonction retourne None ?
- A. mypy lève une erreur
- B. Python lève une erreur à l'exécution
- C. Aucune erreur, mais mypy signale une incohérence
- D. Le type hint est ignoré
Réponse : C — mypy détecte l'incohérence entre l'annotation et le retour effectif.
Q27. Que signifie list[int] comme annotation ?
- A. Une liste qui ne contient que des entiers
- B. Un dictionnaire listant des entiers
- C. Une liste d'entiers (information pour l'analyse statique)
- D. Une liste avec un index entier
Réponse : C — list[int] est un générique annotant le type des éléments pour l'analyse statique.
Q28. Quel module contient Protocol pour le duck typing statique ?
- A.
abc - B.
typing - C.
collections.abc - D.
dataclasses
Réponse : B — typing.Protocol (PEP 544) définit des protocoles pour le duck typing statique.
Q29. Que fait TypeVar('T', bound=float) ?
- A. Définit T comme égal à float
- B. Définit T avec float comme borne supérieure
- C. Définit T comme une sous-classe de float
- D. Définit T comme une liste de float
Réponse : B — bound=float signifie T peut être float ou n'importe quel sous-type.
Q30. Quel type utiliser pour une fonction qui peut retourner soit str, soit None ?
- A.
str | None - B.
Optional[str] - C. Les deux A et B sont valides
- D.
Union[str, None]
Réponse : C — Les deux syntaxes sont équivalentes. str | None (PEP 604) est recommandée.
Q31. Que signifie Final dans from typing import Final ?
- A. La variable ne peut pas être réaffectée
- B. La variable est privée
- C. La variable est globale
- D. La variable est évaluée paresseusement
Réponse : A — Final indique qu'une variable ne doit pas être réaffectée (vérifié par mypy).
Q32. Quelle annotation utiliser pour une fonction qui ne retourne jamais (boucle infinie, levée d'exception) ?
- A.
-> None - B.
-> Never - C.
-> NoReturn - D.
-> Void
Réponse : B ou C — Never (PEP 484) et NoReturn sont tous deux valides, Never est recommandé.
Module 4 : Programmation asynchrone (Q33–Q42)
Q33. Quelle fonction exécute une coroutine et retourne son résultat ?
- A.
async.run() - B.
await - C.
asyncio.run() - D.
coroutine.send()
Réponse : C — asyncio.run() est le point d'entrée standard pour exécuter une coroutine.
Q34. Que se passe-t-il si une exception non gérée survient dans une tâche asyncio ?
- A. La tâche est silencieusement ignorée
- B. L'exception est levée quand on
awaitla tâche - C. Le programme crashe immédiatement
- D. L'exception est loggée automatiquement
Réponse : B — Si la tâche est awaitée, l'exception est propagée. Sinon, elle est stockée dans la tâche.
Q35. Que fait asyncio.gather() si l'une des coroutines lève une exception ?
- A. Toutes les coroutines sont annulées immédiatement
- B. L'exception est levée quand on attend le résultat, les autres continuent
- C. Les coroutines continuent, l'exception est ignorée
- D.
gatherretourneNonepour la coroutine en erreur
Réponse : B — Avec return_exceptions=False (défaut), l'exception est levée immédiatement et les autres tâches continuent.
Q36. Quelle est la différence entre asyncio.create_task() et asyncio.ensure_future() ?
- A. Aucune
- B.
create_task()est plus haut niveau et préféré - C.
ensure_future()lance la coroutine immédiatement - D.
create_task()est synchrone
Réponse : B — create_task() est l'API moderne recommandée. ensure_future() accepte aussi des futures.
Q37. Que retourne une fonction définie avec async def quand elle est appelée ?
- A. Une coroutine
- B. Un Future
- C. Une Task
- D. Le résultat directement
Réponse : A — async def retourne un objet coroutine, pas le résultat.
Q38. Quel context manager asynchrone est utilisé pour créer un groupe de tâches ?
- A.
asyncio.TaskGroup() - B.
asyncio.gather() - C.
asyncio.wait() - D.
asyncio.create_task()
Réponse : A — asyncio.TaskGroup() (Python 3.11+) est un context manager pour gérer des tâches.
Q39. Que fait asyncio.timeout(5) ?
- A. Limite le temps d'exécution d'un bloc à 5 secondes
- B. Met en pause l'exécution pendant 5 secondes
- C. Définit un délai avant l'exécution
- D. Mesure le temps d'exécution
Réponse : A — asyncio.timeout() (Python 3.12+) lève TimeoutError si le dépasse.
Q40. Quelle est la sortie probable de ce code ?
async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(asyncio.sleep(1))
print("Done")
- A.
Doneest imprimé après 1 seconde - B.
Doneest imprimé immédiatement - C. Erreur : les tâches ne sont pas awaitées
- D. Le programme ne termine jamais
Réponse : A — TaskGroup attend que toutes les tâches se terminent avant de sortir du context manager.
Q41. Quel module permet d'écrire du code asynchrone compatible avec asyncio et trio ?
- A.
asyncio - B.
anyio - C.
trio - D.
curio
Réponse : B — anyio fournit une abstraction indépendante de la bibliothèque asynchrone.
Q42. Quel est le problème avec ce code ?
async def fetch_all(urls):
for url in urls:
await fetch(url)
- A. Syntax error
- B. Les appels sont séquentiels, pas concurrents
- C.
fetchdoit être une coroutine - D. Aucun problème
Réponse : B — Les appels sont awaités un par un. Il faut utiliser asyncio.gather() ou TaskGroup.
Module 5 : Web / FastAPI (Q43–Q52)
Q43. Quel décorateur crée une route GET dans FastAPI ?
- A.
@app.get() - B.
@app.route('/path', methods=['GET']) - C.
@app.get('/path') - D.
@api.get('/path')
Réponse : C — @app.get('/path') est la syntaxe FastAPI pour une route GET.
Q44. Quel module FastAPI utilise pour la validation des données ?
- A.
json - B.
pydantic - C.
marshmallow - D.
attrs
Réponse : B — FastAPI s'appuie sur Pydantic pour la validation des modèles de données.
Q45. Que retourne Query(ge=1, le=100) dans un paramètre de fonction ?
- A. Un paramètre de requête optionnel
- B. Un paramètre de requête avec validation (≥1 et ≤100)
- C. Une query SQL
- D. Un paramètre de chemin
Réponse : B — Query(ge=1, le=100) valide que le paramètre est entre 1 et 100.
Q46. Que fait Depends() dans FastAPI ?
- A. Déclare une dépendance obligatoire
- B. Injecte le résultat d'une fonction comme paramètre
- C. Déclare un middleware
- D. Ajoute une route dépendante
Réponse : B — Depends() est le mécanisme d'injection de dépendances de FastAPI.
Q47. Quel est le bon code de statut HTTP pour une création réussie ?
- A. 200
- B. 201
- C. 202
- D. 204
Réponse : B — 201 Created est le code standard pour une création réussie.
Q48. Quel schéma OAuth2 FastAPI utilise-t-il pour protéger les routes ?
- A.
OAuth2PasswordBearer - B.
OAuth2AuthorizationCode - C.
OAuth2ClientCredentials - D.
OAuth2Implicit
Réponse : A — OAuth2PasswordBearer est le schéma intégré pour le flow password.
Q49. Comment FastAPI génère-t-il automatiquement la documentation ?
- A. Javadoc
- B. Sphinx
- C. Swagger UI (OpenAPI) et ReDoc
- D. MkDocs
Réponse : C — FastAPI expose automatiquement Swagger UI sur /docs et ReDoc sur /redoc.
Q50. Que permet responses_model dans un décorateur de route ?
- A. Définir le modèle de réponse pour la validation
- B. Définir le modèle de requête
- C. Définir le modèle de base de données
- D. Définir le modèle de template
Réponse : A — response_model valide et filtre la réponse selon le modèle Pydantic.
Q51. Quel décorateur WebSocket FastAPI doit-on utiliser ?
- A.
@app.websocket('/ws') - B.
@app.ws('/ws') - C.
@app.socket('/ws') - D.
@app.ws_route('/ws')
Réponse : A — @app.websocket('/ws') définit une route WebSocket.
Q52. Que retourne HTTPException(status_code=404) dans FastAPI ?
- A. Une réponse JSON avec une erreur
- B. Une page HTML 404
- C. Une redirection
- D. Une exception Python standard
Réponse : A — FastAPI convertit automatiquement HTTPException en réponse JSON.
Module 6 : Data (pandas, numpy) (Q53–Q62)
Q53. Que retourne df.head() sur un DataFrame pandas ?
- A. Les 5 premières lignes
- B. Les 5 dernières lignes
- C. Les statistiques descriptives
- D. Le nom des colonnes
Réponse : A — Par défaut, head() retourne les 5 premières lignes.
Q54. Quelle méthode pandas supprime les lignes avec des valeurs manquantes ?
- A.
df.fillna() - B.
df.dropna() - C.
df.drop() - D.
df.remove_na()
Réponse : B — dropna() supprime les lignes contenant des NaN.
Q55. Quelle est la sortie de pd.Series([1, 2, 3]).mean() ?
- A. 1.0
- B. 2.0
- C. 3.0
- D. 6.0
Réponse : B — La moyenne de 1, 2, 3 est 2.0.
Q56. Comment regrouper par une colonne et calculer la moyenne ?
- A.
df.groupby('col').mean() - B.
df.group('col').avg() - C.
df.aggregate('col', 'mean') - D.
df.pivot('col').mean()
Réponse : A — groupby('col').mean() est la syntaxe pandas standard.
Q57. Que fait pd.merge(df1, df2, on='id', how='left') ?
- A. Concatène df1 et df2 verticalement
- B. Joint df1 et df2 sur la colonne id, gardant toutes les lignes de df1
- C. Joint df1 et df2 sur la colonne id, gardant seulement les intersections
- D. Fusionne les colonnes de df1 et df2
Réponse : B — how='left' garde toutes les lignes de la table de gauche (df1).
Q58. Quel est l'avantage de numpy par rapport aux listes Python ?
- A. Vérification de type à la compilation
- B. Opérations vectorisées plus rapides
- C. Gestion automatique de la mémoire
- D. Support natif du multithreading
Réponse : B — numpy utilise des opérations vectorisées en C, bien plus rapides que les boucles Python.
Q59. Que retourne df['col'].value_counts() ?
- A. Le nombre de valeurs uniques
- B. Le comptage de chaque valeur distincte
- C. Les valeurs triées
- D. Les statistiques descriptives
Réponse : B — value_counts() compte les occurrences de chaque valeur distincte.
Q60. Comment appliquer une fonction à chaque élément d'une colonne pandas ?
- A.
df['col'].apply(func) - B.
df['col'].map(func) - C.
df['col'].transform(func) - D. Les deux A et B fonctionnent
Réponse : D — apply() et map() peuvent toutes deux appliquer une fonction élément par élément.
Q61. Que retourne pd.to_datetime('2024-01-15') ?
- A.
Timestamp('2024-01-15') - B.
'2024-01-15' - C.
datetime(2024, 1, 15) - D.
date(2024, 1, 15)
Réponse : A — pd.to_datetime() retourne un objet Timestamp pandas.
Q62. Quelle méthode calcule la matrice de corrélation d'un DataFrame ?
- A.
df.cov() - B.
df.corr() - C.
df.correlate() - D.
df.correlation()
Réponse : B — df.corr() calcule la matrice de corrélation de Pearson.
Module 7 : Machine Learning (Q63–Q70)
Q63. Que fait train_test_split() de scikit-learn ?
- A. Divise les données en features et target
- B. Divise les données en ensembles d'entraînement et de test
- C. Normalise les données
- D. Standardise les données
Réponse : B — train_test_split() partitionne aléatoirement en training et test sets.
Q64. Quel métrique est appropriée pour un problème de classification binaire déséquilibré ?
- A. Accuracy
- B. F1-score
- C. Mean Absolute Error
- D. R²
Réponse : B — Le F1-score est préféré pour les datasets déséquilibrés car il combine précision et rappel.
Q65. Que fait StandardScaler dans un pipeline ?
- A. Supprime les valeurs aberrantes
- B. Centre et réduit les features (moyenne=0, variance=1)
- C. Normalise entre 0 et 1
- D. Convertit les catégories en nombres
Réponse : B — StandardScaler standardise les features : (x - μ) / σ.
Q66. Quel est le risque principal du Grid Search avec trop de paramètres ?
- A. Underfitting
- B. Overfitting (data leakage)
- C. Temps d'exécution exponentiel
- D. Instabilité numérique
Réponse : C — Le nombre de combinaisons croît exponentiellement avec le nombre de paramètres.
Q67. Que fait cross_val_score() ?
- A. Évalue un modèle avec validation croisée
- B. Calcule les scores de corrélation croisée
- C. Valide les features sélectionnées
- D. Croise les résultats de plusieurs modèles
Réponse : A — cross_val_score() applique la validation croisée et retourne les scores.
Q68. Quel est l'avantage de RandomForestClassifier sur un arbre de décision simple ?
- A. Plus rapide à l'entraînement
- B. Moins de variance, meilleure généralisation
- C. Plus simple à interpréter
- D. Nécessite moins de données
Réponse : B — Random Forest réduit la variance en moyennant plusieurs arbres.
Q69. Que signifie "overfitting" ?
- A. Le modèle est trop simple
- B. Le modèle apprend trop bien les données d'entraînement mais généralise mal
- C. Le modèle est trop lent
- D. Le modèle nécessite plus de features
Réponse : B — L'overfitting est un apprentissage excessif du bruit des données d'entraînement.
Q70. Quelle classe de scikit-learn permet de créer des pipelines de transformations et d'estimateurs ?
- A.
Pipeline - B.
Chain - C.
Flow - D.
Sequential
Réponse : A — sklearn.pipeline.Pipeline enchaîne transformations et modèle final.
Module 8 : Architecture logicielle (Q71–Q78)
Q71. Quel principe SOLID stipule qu'une classe ne doit avoir qu'une seule raison de changer ?
- A. Open/Closed Principle
- B. Single Responsibility Principle
- C. Liskov Substitution Principle
- D. Dependency Inversion Principle
Réponse : B — SRP : chaque classe doit avoir une seule responsabilité.
Q72. Que signifie "injection de dépendances" ?
- A. Créer des dépendances à l'intérieur d'une classe
- B. Fournir les dépendances d'une classe de l'extérieur
- C. Supprimer les dépendances d'une classe
- D. Tester les dépendances d'une classe
Réponse : B — La DI consiste à passer les dépendances via le constructeur ou les paramètres.
Q73. Quel pattern permet de séparer la logique métier de la persistance ?
- A. Singleton
- B. Repository
- C. Factory
- D. Observer
Réponse : B — Le Repository pattern abstrait la couche de persistance.
Q74. Que représente une "Entity" dans la Clean Architecture ?
- A. Un objet métier avec une identité unique
- B. Une table de base de données
- C. Une classe utilitaire
- D. Un DTO
Réponse : A — Une Entity est un objet métier avec une identité (id) et une continuité.
Q75. Quel est le rôle d'un "Use Case" dans la Clean Architecture ?
- A. Gérer la persistance
- B. Orchestrer les opérations métier
- C. Gérer les requêtes HTTP
- D. Configurer l'application
Réponse : B — Un Use Case coordonne les entités pour réaliser une opération métier.
Q76. Que permet CQRS (Command Query Responsibility Segregation) ?
- A. Séparer les lectures et écritures
- B. Séparer le frontend et backend
- C. Séparer la base de données de l'application
- D. Séparer les tests unitaires et d'intégration
Réponse : A — CQRS utilise des modèles différents pour les commandes (écritures) et les queries (lectures).
Q77. Quel est l'avantage de l'architecture microservices ?
- A. Simplicité du déploiement
- B. Scalabilité indépendante des services
- C. Base de données unique
- D. Communication synchrone
Réponse : B — Les microservices peuvent être scalés indépendamment selon la charge.
Q78. Quel outil est utilisé pour gérer les migrations de base de données en Python ?
- A. Git
- B. Alembic
- C. Docker
- D. pip
Réponse : B — Alembic (par SQLAlchemy) gère les migrations de schéma de base de données.
Module 9 : Sécurité (Q79–Q86)
Q79. Quelle attaque consiste à injecter du code SQL via des entrées utilisateur ?
- A. XSS
- B. SQL Injection
- C. CSRF
- D. SSRF
Réponse : B — L'injection SQL exploite des entrées non sanitizées dans les requêtes SQL.
Q80. Comment prévenir l'injection SQL avec SQLAlchemy ?
- A. Utiliser des chaînes formatées
- B. Utiliser des requêtes paramétrées (texte avec bind params)
- C. Échapper les guillemets manuellement
- D. Utiliser
eval()
Réponse : B — Les requêtes paramétrées avec bindparam() empêchent l'injection SQL.
Q81. Que signifie JWT ?
- A. JavaScript Web Token
- B. JSON Web Token
- C. Java Web Token
- D. JSON With Token
Réponse : B — JWT est un standard ouvert (RFC 7519) pour les tokens d'authentification.
Q82. Où stocker un secret d'application (clé API, mot de passe) ?
- A. Dans le code source
- B. Dans les variables d'environnement ou un gestionnaire de secrets
- C. Dans la base de données
- D. Dans les logs
Réponse : B — Les secrets doivent être stockés dans des variables d'environnement ou un vault.
Q83. Quelle attaque CSRF exploite-t-elle ?
- A. La confiance qu'un site a dans le navigateur de l'utilisateur
- B. La confiance qu'un site a dans l'utilisateur
- C. La confiance qu'un utilisateur a dans un site
- D. Les failles XSS
Réponse : A — CSRF force l'utilisateur à exécuter des actions non désirées sur un site où il est authentifié.
Q84. Comment FastAPI protège-t-il contre les attaques par déni de service ?
- A. Rate limiting intégré
- B. Limitation de taille de requête via
max_size - C. Aucune protection intégrée, nécessite un middleware
- D. Validation des types
Réponse : C — FastAPI n'a pas de rate limiting intégré. Il faut utiliser un middleware ou un reverse proxy.
Q85. Quelle bibliothèque Python est utilisée pour scanner les vulnérabilités de sécurité ?
- A. pytest
- B. bandit
- C. black
- D. isort
Réponse : B — Bandit est un analyseur de sécurité statique pour Python.
Q86. Quel est le principe de "défense en profondeur" ?
- A. Utiliser un seul mécanisme de sécurité très fort
- B. Superposer plusieurs couches de sécurité
- C. Sécuriser uniquement le périmètre réseau
- D. Faire confiance aux systèmes internes
Réponse : B — La défense en profondeur multiplie les barrières de sécurité.
Module 10 : DevOps & Docker (Q87–Q94)
Q87. Quel est l'avantage d'un Dockerfile multi-stage ?
- A. Réduire la taille de l'image finale
- B. Augmenter la vitesse de build
- C. Permettre le déploiement sur plusieurs OS
- D. Faciliter le debugging
Réponse : A — Multi-stage sépare l'environnement de build (volumineux) de l'image runtime (minimale).
Q88. Que fait l'instruction HEALTHCHECK dans un Dockerfile ?
- A. Vérifie la santé du processus hôte
- B. Définit une commande pour tester que le conteneur fonctionne
- C. Installe des outils de santé
- D. Vérifie les mises à jour de sécurité
Réponse : B — HEALTHCHECK permet à Docker de surveiller l'état du conteneur.
Q89. Quel est le but d'un CI/CD pipeline ?
- A. Déployer manuellement les applications
- B. Automatiser les tests et le déploiement
- C. Écrire le code à la place du développeur
- D. Gérer les bases de données
Réponse : B — CI/CD automatise l'intégration, les tests et le déploiement du code.
Q90. Que fait pytest --cov=src ?
- A. Exécute les tests en parallèle
- B. Mesure la couverture de code du dossier src
- C. Ignore les tests échoués
- D. Génère un rapport HTML
Réponse : B — --cov=src active la mesure de couverture pour le module src.
Q91. Quel outil est utilisé pour le linting Python dans ce projet ?
- A. flake8
- B. pylint
- C. ruff
- D. black
Réponse : C — Ce projet utilise ruff pour le linting et le formatting.
Q92. Que fait docker-compose up -d ?
- A. Construit et démarre les services en arrière-plan
- B. Démarre les services au premier plan
- C. Arrête les services
- D. Supprime les conteneurs
Réponse : A — -d (detach) démarre les conteneurs en arrière-plan.
Q93. Quel fichier configure les hooks de pre-commit ?
- A.
pyproject.toml - B.
.pre-commit-config.yaml - C.
.github/workflows/ci.yml - D.
setup.cfg
Réponse : B — .pre-commit-config.yaml configure les hooks pre-commit.
Q94. Quelle commande Makefile exécute la suite complète de vérification (lint + test + security) ?
- A.
make lint - B.
make all - C.
make test - D.
make verify
Réponse : B — make all exécute lint, test et security en séquence.
Module 11 : Python avancé (Q95–Q100)
Q95. Que permet une métaclasse ?
- A. Créer des classes de manière dynamique
- B. Modifier le comportement des instances
- C. Personnaliser la création des classes
- D. Ajouter des attributs aux instances
Réponse : C — Une métaclasse est une classe de classe qui personnalise la création des classes.
Q96. Quelle méthode est appelée par obj.attr = value ?
- A.
__getattr__ - B.
__setattr__ - C.
__delattr__ - D.
__getattribute__
Réponse : B — __setattr__(self, name, value) est appelée lors de l'affectation d'un attribut.
Q97. Que retourne eval("2 + 3 * 4") ?
- A. 20
- B. 14
- C. 24
- D. 9
Réponse : B — eval() exécute l'expression Python. Priorité des opérateurs : 3 * 4 = 12, 2 + 12 = 14.
Q98. Que fait un "descriptor" en Python ?
- A. Décrit une classe avec des métadonnées
- B. Définit
__get__,__set__,__delete__pour contrôler l'accès aux attributs - C. Sérialise une classe en JSON
- D. Décore une fonction avec des informations de typage
Réponse : B — Un descriptor implémente le protocole des descripteurs (__get__/__set__/__delete__).
Q99. Que permet le module ast en Python ?
- A. Analyser et manipuler l'arbre syntaxique abstrait du code Python
- B. Générer des nombres aléatoires
- C. Effectuer des calculs statistiques
- D. Gérer les expressions asynchrones
Réponse : A — ast permet de parser, analyser et transformer le code Python.
Q100. Quelle est la sortie de ce code ?
class Meta(type):
def __new__(mcs, name, bases, namespace):
namespace['added'] = True
return super().__new__(mcs, name, bases, namespace)
class A(metaclass=Meta):
pass
print(A.added)
- A.
True - B.
False - C.
AttributeError - D.
None
Réponse : A — La métaclasse Meta ajoute added = True au namespace de la classe lors de sa création.
Grille de correction
Utilisez la grille ci-dessous pour compter vos points :
| Questions | Réponses exactes | Score |
|---|---|---|
| Q01-Q15 | .../15 | |
| Q16-Q25 | .../10 | |
| Q26-Q32 | .../7 | |
| Q33-Q42 | .../10 | |
| Q43-Q52 | .../10 | |
| Q53-Q62 | .../10 | |
| Q63-Q70 | .../8 | |
| Q71-Q78 | .../8 | |
| Q79-Q86 | .../8 | |
| Q87-Q94 | .../8 | |
| Q95-Q100 | .../6 | |
| Total | .../100 |
Rendez-vous au chapitre 19 pour les corrigés détaillés de chaque question.