From 2368e4d4101dbbbc65b1e82c9b847b194c7a47e6 Mon Sep 17 00:00:00 2001 From: Dimitri Merejkowsky Date: Sat, 7 Dec 2019 12:23:35 +0100 Subject: [PATCH] =?UTF-8?q?=C3=89pisode=207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- saison-2/sessions/Makefile | 2 +- saison-2/sessions/python-S02-E07.md | 363 ++++++++++++++++++++++++++++ 2 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 saison-2/sessions/python-S02-E07.md diff --git a/saison-2/sessions/Makefile b/saison-2/sessions/Makefile index e8e040c..cc40e4a 100644 --- a/saison-2/sessions/Makefile +++ b/saison-2/sessions/Makefile @@ -1,4 +1,4 @@ -all: python-S02-E06.pdf +all: python-S02-E07.pdf %.pdf: %.md pandoc --pdf-engine=xelatex -t beamer $< -o $@ diff --git a/saison-2/sessions/python-S02-E07.md b/saison-2/sessions/python-S02-E07.md new file mode 100644 index 0000000..d78780b --- /dev/null +++ b/saison-2/sessions/python-S02-E07.md @@ -0,0 +1,363 @@ +% Programmation avec Python (Épisode 7) +% Dimitri Merejkowsky + + +\center \huge Rappels + + +# Classes vides + +Définition: +```python +class MaClasse: + pass +``` + +Instanciation: +```python +>>> instance_1 = MaClasse() +``` + +# Attributs + +Un attribut est une variable _à l'intérieur_ d'autre chose (par exemple une instance de classe). + +```python +>>> mon_instance = MaClasse() +# création de l'attribut `x` dans mon_instance: +>>> mon_instance.x = 42 +# accès à l'attribut `x` dans mon_instance: +>>> mon_instance.x +42 +``` + +# Méthodes + +Une méthode est une fonction définie à l'intérieur d'une classe: + +Définition: +```python +class MaClasse: + def ma_méthode(self): + return 42 +``` + +Les méthodes sont des attributs des instances de classes: + +```python +class MaClasse: + def ma_méthode(self): + return 42 +>>> ma_méthode() +Erreur +>>> mon_instance = MaClasse() +>>> mon_instance.ma_méthode() +42 +``` + + +# self + +`self` *prend la valeur de l'instance courante* quand la méthode est appelée. + +```python +class MaClasse: + def affiche_attribut_x(self): + print(self.x) + +>>> mon_instance = MaClasse() +>>> mon_instance.x = 42 +>>> mon_instance.affiche_attribut_x() +42 +``` + +# self (2) + +On peut aussi *créer* des attributs dans une méthode: + +```python +class MaClasse: + def crée_attribut_x(self): + self.x = 42 + def affiche_attribut_x(self): + print(self.x) + +>>> mon_instance = MaClasse() +>>> mon_instance.affiche_attribut_x() +# Erreur: `mon_instance` n'a pas d'attribut `x` + +>>> mon_instance.crée_attribut_x() +>>> mon_instance.affiche_attribut_x() +42 +``` + +# Méthodes avec arguments + +```python +class MaClasse + def crée_attribut_x(self, valeur_de_x): + self.x = valeur_de_x + + def affiche_attribut_x(self); + print(self.x) + +>>> mon_instance = MaClasse() +>>> mon_instance.crée_attribut_x(42) +>>> mon_instance.affiche_attribut_x() +42 +``` + +# Méthodes appelant d'autres méthodes + +```python +class MaClasse: + def méthode_1(self): + print("démarrage de la méthode 1") + print("la méthode 1 affiche bonjour") + print("bonjour") + print("fin de la méthode 1") + + + def méthode_2(self): + print("la méthode 2 appelle la méthode 1") + self.méthode_1() + print("fin de la méthode 2") +``` + + +```python +>>> mon_instance = MaClasse() +>>> mon_instance.méthode_2() +``` + +```text +la méthode 2 appelle la méthode 1 +démarrage de la méthode 1 +la méthode 1 affiche bonjour +bonjour +fin de la méthode 1 +fin de la méthode 2 +``` + +# Constructeur sans arguments + +Un constructeur en Python désigne la méthode nomée `__init__`, +quand celle-ci existe. + +La méthode `__init__` est appelée automatiquement quand la +classe est instanciée: + +```python +class MaClasse: + def __init__(self): + self.x = 1 + self.y = 2 + +>>> mon_instance = MaClasse() +>>> mon_instance.x +1 +>>> mon_instance.y +2 +``` + +# Constructeur avec arguments + +La méthode `__init__` peut avoir des arguments, +dans ce cas, ceux ci doivent être fournis +lors de l'instanciation: + +```python +class MaClasse: + def __init__(self, x, y): + self.x = x + self.y = y +``` + +```python +>>> mon_instance = MaClasse(3, 4) +>>> mon_instance.x +3 +>>> mon_instance.y +4 +``` + +# Couplage (1) + +## Définition + +Un couplage décrit une relation entre deux classes. + +## Exemple + +Ici on veut représenter des chats et des humains qui adoptent (on non) des chats. +Tous les chats ont un nom, et tous les humains ont un prénom. + +On peut utiliser pour cela deux classes: `Chat` et `Humain`: + +# Couplage (2) + + +```python +class Chat: + def __init__(self, nom): + self.nom = nom + +>>> chat = Chat("Monsieur Moustaches") +>>> chat.nom +'Monsieur Moustaches' +``` + +```python +class Humain: + def __init__(self, prénom): + self.prénom = prénom +>>> alice = Humain(prénom="Alice") +>>> alice.prénom +"Alice" +``` + +# + +Maintenant on veut que les humains puissent adopter des chats. +Pour cela, on peut rajouter la méthode `adopte` dans la classe +`Humain`. + +Cette méthode va prendre un argument - une instance de la +classe `Chat`: + +```python +class Humain: + def __init__(self, prénom): + self.prénom = prénom + + def adopte(self, chat): + print(self.prénom, "adopte un chat") + +>>> boule_de_poils = Chat("Boule de Poils") +>>> alice = Humain("Alice") +>>> alice.adopte(boule_de_poils) +"Alice adopte un chat" +``` + +# + +On peut accéder au nom du chat depuis la méthode `adopte`, +en utilisant la syntaxe `nom.attribut` vue précédemment: + +```python +class Humain: + def __init__(self, prénom): + self.prénom = prénom + + def adopte(self, chat): + print(self.prénom, "adopte", chat.nom) + +>>> boule_de_poils = Chat("Boule de Poils") +>>> alice = Humain("Alice") +>>> alice.adopte(boule_de_poils) +"Alice adopte Boule de Poils" +``` + +# Couplage + +```python +class Humain: + ... + def adopte(self, chat): + print(self.prénom, "adopte", chat.nom) +``` + +Notez également que nous avons écrit `chat.nom`. ainsi, la méthode `adopte()` +ne peut être appelée que part une instance qui a un attribut `nom` - sinon +on aura une erreur. + +Donc si on modifie la classe `Chat` et qu'on renomme l'attribut `nom` en `surnom` par exemple, +la méthode `adopte()` de la classe `Humain` cessera de fonctionner: on dit +qu'on a un *couplage* entre les classes `Chat` et `Humain`. + +# Couplage entre fonctions + +```python +largeur = demander_largeur() +dessine_sapin(largeur) +``` + + +\vfill + +* `dessine_sapin()` prend un argument `largeur`, retourné par `demander_largeur()`. +* `dessine_sapin()` _dépend_ de `demander_largeur()` + +# Dépendances entre classes (1) + +```python +class Chat: + def __init__(self, nom): + self.nom = nome +``` + +On ne peut pas construire des chats sans nom: + +```python +>>> chat = Chat() +TypeError: __init__() missing 1 required positional + argument: 'nom' +``` + + +# Dépendances entre classes (2) + +Tous les enfants ont un chat! + +```python +class Enfant: + def __init__(self, prénom, chat): + self.prénom = prénom + self.chat = chat + +>>> alice = Enfant("Alice") +TypeError: __init__() missing 1 required positional + argument: 'chat' + +>>> boule_de_poils = Chat("Boule de Poils") +>>> alice = Enfant("Alice", boule_de_poils) +# OK! +``` + +# Utilisation de la composition + + +```python +class Chat: + def __init__(self, nom): + self.nom = nom + + def ronronne(self): + print(self.nom, 'fait: "prrrrr"') + + def caresse(self): + self.ronronne() + + +>>> boule_de_poils = Chat("Boule de Poils") +>>> boule_de_poils.caresse() +Boule de Poils fait "prrrrr" +``` + +# Composition (2) + +```python +class Enfant: + def __init__(self, prénom, chat): + self.chat = chat + + def console(self): + self.chat.caresse() + +>>> boule_de_poils = Chat("Boule de Poils") +>>> alice = Enfant("Alice", boule_de_poils) +# Alice est triste, on la console +>>> alice.console() +Boule de Poils fait "prrrrr" +# Alice est consolée :) +```