Review cours Terminale NSI — POO, SQL, Sécurité, Soc, Calculabilité, Réseau

This commit is contained in:
2026-06-15 11:28:37 +02:00
parent fcb20e45f9
commit 9ad5b99920
9 changed files with 1305 additions and 827 deletions

View File

@@ -248,6 +248,88 @@ Ces méthodes sont appelées des accesseurs et modificateurs. Elles sont optionn
-----------
## L'héritage
Jusqu'ici, nous avons créé des classes indépendantes les unes des autres. Mais en POO, il est possible de créer une classe à partir d'une autre classe existante : c'est le principe de l'**héritage**.
L'idée est simple : une classe **enfant** hérite de tous les attributs et méthodes d'une classe **parent**, et peut en ajouter de nouveaux ou en modifier certains.
> L'héritage modélise une relation **"est-un"** : un `EtudiantBoursier` **est un** `Etudiant`. À ne pas confondre avec la composition vue dans le TP Pokémon, qui modélise une relation **"a-un"** : un `Dresseur` **a des** `Pokemon`.
### Syntaxe de base
Supposons que l'on veuille créer un `EtudiantBoursier` qui est un `Etudiant` avec une bourse mensuelle en plus.
```python
class EtudiantBoursier(Etudiant):
def __init__(self, nom_etu, prenom_etu, spe1_etu, age_etu, bourse_mensuelle):
super().__init__(nom_etu, prenom_etu, spe1_etu, age_etu)
self.bourse = bourse_mensuelle
```
Plusieurs choses à noter :
- `class EtudiantBoursier(Etudiant)` : on indique entre parenthèses la classe parent dont on hérite.
- `super().__init__(...)` : on appelle le constructeur de la classe parent pour initialiser les attributs déjà définis. Cela évite de tout réécrire.
- On ajoute ensuite les attributs propres à l'enfant (`self.bourse`).
```python
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
>>> eb.nom
'Martin'
>>> eb.bourse
250
>>> eb.peut_avoir_son_permis
False
```
L'objet `eb` a accès à tous les attributs de `Etudiant` **et** à `bourse`.
### Surcharge de méthode
Un `EtudiantBoursier` peut avoir besoin d'une méthode `__repr__` différente de celle de `Etudiant`. On peut alors **surcharger** (redéfinir) la méthode dans la classe enfant :
```python
class EtudiantBoursier(Etudiant):
def __init__(self, nom_etu, prenom_etu, spe1_etu, age_etu, bourse_mensuelle):
super().__init__(nom_etu, prenom_etu, spe1_etu, age_etu)
self.bourse = bourse_mensuelle
def __repr__(self):
return super().__repr__() + f' (boursier : {self.bourse}€/mois)'
```
```python
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
>>> eb
Martin Léa (boursier : 250/mois)
```
Ici `super().__repr__()` appelle la version de la classe parent pour ne pas dupliquer le code.
### isinstance()
La fonction native `isinstance()` permet de vérifier si un objet est une instance d'une classe donnée — y compris via l'héritage :
```python
>>> eb = EtudiantBoursier('Martin', 'Léa', 'NSI', 17, 250)
>>> isinstance(eb, EtudiantBoursier)
True
>>> isinstance(eb, Etudiant)
True
```
`eb` est à la fois un `EtudiantBoursier` ET un `Etudiant`. C'est la conséquence directe de l'héritage.
### Exercices
1. Créez une classe `EtudiantInternational` qui hérite de `Etudiant` et possède un attribut supplémentaire `pays_origine`.
2. Surchargez `__repr__` pour afficher le pays entre parenthèses.
3. Créez une fonction `liste_internationaux(etudiants)` qui prend une liste d'`Etudiant` et renvoie uniquement les `EtudiantInternational`. Utilisez `isinstance()`.
4. Que se passe-t-il si on appelle `anniversaire()` sur un `EtudiantBoursier` ? Pourquoi ?
-----------
Auteurs : Florian Mathieu, Enzo Frémeaux, Thimothée Decooster
Licence CC BY NC

View File

@@ -398,14 +398,107 @@ Modifiez la classe `Pokemon` pour qu'un Pokémon possède une liste de capacité
---
## Partie 5 : Héritage — Spécialiser les Pokémon
> **Prérequis** : avoir vu le cours sur l'héritage.
Jusqu'ici, tous les Pokémon utilisent la même méthode `attaquer`. Mais en vrai, un Pokémon Feu n'attaque pas comme un Pokémon Eau. Plutôt que de gérer ça avec un dictionnaire de faiblesses dans `attaquer`, on peut utiliser l'**héritage** pour créer des sous-classes spécialisées.
---
### Exercice 8 : Sous-classes par type
Créez trois sous-classes qui héritent de `Pokemon` :
- `PokemonFeu` : inflige ×2 dégâts aux Pokémon Plante
- `PokemonEau` : inflige ×2 dégâts aux Pokémon Feu
- `PokemonPlante` : inflige ×2 dégâts aux Pokémon Eau
Chaque sous-classe doit :
1. Hériter de `Pokemon` via `class PokemonFeu(Pokemon):`
2. Appeler `super().__init__(...)` dans son constructeur en fixant `type_pokemon` automatiquement
3. Surcharger la méthode `attaquer` pour appliquer le bonus de dégâts
```python
class PokemonFeu(Pokemon):
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
super().__init__(nom, "Feu", niveau, pv_max, attaque)
def attaquer(self, cible):
"""
Attaque avec ×2 dégâts si la cible est de type Plante.
"""
# À compléter
pass
class PokemonEau(Pokemon):
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
super().__init__(nom, "Eau", niveau, pv_max, attaque)
def attaquer(self, cible):
"""
Attaque avec ×2 dégâts si la cible est de type Feu.
"""
# À compléter
pass
class PokemonPlante(Pokemon):
def __init__(self, nom, niveau=1, pv_max=100, attaque=10):
super().__init__(nom, "Plante", niveau, pv_max, attaque)
def attaquer(self, cible):
"""
Attaque avec ×2 dégâts si la cible est de type Eau.
"""
# À compléter
pass
```
**Tests :**
```python
>>> salameche = PokemonFeu("Salamèche", niveau=15, pv_max=70, attaque=12)
>>> bulbizarre = PokemonPlante("Bulbizarre", niveau=15, pv_max=75, attaque=10)
>>> salameche.attaquer(bulbizarre)
C'est super efficace !
Salamèche attaque Bulbizarre et inflige 24 dégâts !
>>> bulbizarre.attaquer(salameche)
Bulbizarre attaque Salamèche et inflige 10 dégâts !
```
---
### Exercice 9 : isinstance() en pratique
1. Vérifiez que `salameche` est à la fois une instance de `PokemonFeu` **et** de `Pokemon`. Expliquez pourquoi.
2. Écrivez une fonction `compter_par_type(equipe)` qui prend une liste de Pokémon et renvoie un dictionnaire `{type: nombre}`.
```python
>>> equipe = [PokemonFeu("Dracaufeu"), PokemonEau("Tortank"), PokemonFeu("Sulfura"), PokemonPlante("Florizarre")]
>>> compter_par_type(equipe)
{'Feu': 2, 'Eau': 1, 'Plante': 1}
```
---
### Exercice 10 : Refactoring
Relisez le dictionnaire `FAIBLESSES` de l'exercice 3. Maintenant que vous avez des sous-classes, ce dictionnaire est-il encore utile ? Quelle approche est plus lisible selon vous ? Discutez.
---
## Résumé des classes
| Classe | Attributs | Méthodes principales |
|--------|-----------|----------------------|
| `Pokemon` | nom, type, niveau, pv, attaque | attaquer(), subir_degats(), est_ko() |
| `Dresseur` | nom, equipe | ajouter_pokemon(), tous_ko() |
| `Combat` | dresseur1, dresseur2, tour | lancer_combat() |
| `CentrePokemon` | ville | soigner_equipe() |
| Classe | Hérite de | Attributs supplémentaires | Méthodes modifiées |
|--------|-----------|---------------------------|--------------------|
| `Pokemon` | — | nom, type, niveau, pv, attaque | attaquer(), subir_degats(), est_ko() |
| `PokemonFeu` | `Pokemon` | — | attaquer() |
| `PokemonEau` | `Pokemon` | — | attaquer() |
| `PokemonPlante` | `Pokemon` | — | attaquer() |
| `Dresseur` | — | nom, equipe | ajouter_pokemon(), tous_ko() |
| `Combat` | — | dresseur1, dresseur2, tour | lancer_combat() |
| `CentrePokemon` | — | ville | soigner_equipe() |
---