diff --git a/saison-2/sessions/Makefile b/saison-2/sessions/Makefile index cb72cf1..c61109b 100644 --- a/saison-2/sessions/Makefile +++ b/saison-2/sessions/Makefile @@ -1,4 +1,4 @@ -all: python-S02-E04.pdf +all: python-S02-E05.pdf %.pdf: %.md pandoc --pdf-engine=xelatex -t beamer $< -o $@ diff --git a/saison-2/sessions/python-S02-E05.md b/saison-2/sessions/python-S02-E05.md new file mode 100644 index 0000000..16f75d0 --- /dev/null +++ b/saison-2/sessions/python-S02-E05.md @@ -0,0 +1,369 @@ +% Programmation avec Python (chapitre 5) +% Dimitri Merejkowsky + + +# + +\center \huge Rappels sur les fonctions + +# Exemple 1 + +```python +# Définition d'une fonction sans arguments +def ma_fonction(): + print("ma_fonction commence ...") + print("bonjour") + print("ma_fonction finit.") + +# Appel de la fonction `ma_fonction`: +>>> ma_fonction() +ma_fonction commence ... +bonjour +ma_fonction finit. +``` + +# Exemple 2 + +```python +# Définition d'une fonction avec un argument, x: +def ma_fonction(x): + print("x vaut", x) + +# Appel de la fonction `ma_fonction`: +>>> ma_fonction(42) +x vaut 42 +``` + +# Changement de paradigme + +Ce qu’on a vu jusqu’ici: + +* Des types simples (entiers, booléens, ...) +* Des structures de données (listes, dictionnaires, ...) +* Des fonctions qui manipulent ces types ou ces types +* Des fonctions qui s’appellent les unes les autres + +On appelle cet ensemble de concepts, cette façon d'écrire du code, un *paradigme* - +et c'est un paradigme *procédural*. + +On va passer à un autre paradigme: l'*orienté objet*. + +# Orienté objet - une première définition + +Un "objet" informatique *représente* un véritable "objet" physique +dans le vrai monde véritable. + +Ce n'est pas une très bonne définition: + +1. Ce n'est pas nécessaire +2. Ce n'est même pas forcément souhaitable! + +Je le mentionne juste parce que c'est une idée reçue très répandue. + +# Orienté objet - 2ème définition + +Mettre au même endroit: + +* des données +* des fonctions qui opèrent sur ces données + +L'important c'est que les deux aillent ensemble! + + +# Orienté objet - 3ème définition + +Des "cellules" qui s'envoient des "messages". + +Notamment, les cellules ne "voient" que leur état interne. + +On peut envoyer un message d'une cellule à une autre *sans* connaître +beaucoup de détails à propos du destinataire du message. + +On a déjà vu ce concepts avec des fonctions fonctionnant en mode +*boîte noire* du point de vue du code qui les appelle. + + +# Les classes + +On va parler *d'une* façon de faire de l'orienté objet: avec des classes. + +Mais notez bien qu'on peut faire de l'orienté objet *sans* classes! + +# Le plan de construction + +La seule chose dont on a besoin pour construire un objet, c'est d'un *plan de construction*. + +On appelle ce plan une *classe* et on la définit ainsi: + +```python +class MonObjet: + pass +``` + +Ça ressemble un peu à la définition d'une fonction. Les noms des classes commencent souvent +par une majuscule. + + +# Créons des objets + +On crée un objet en mettant le nom de la classe suivi d'une paire de parenthèses - +un peu comme pour appeler une fonction: + +```python +>>> objet_1 = MonObjet() +``` + +Ici, `objet_1` est une *instance* de la classe `MonObjet`. + +# Attributs + +Les attributs sont des éléments _nommés_ "à l'intérieur" d'un objet. + +On peut y accéder avec la syntaxe `.`: + +```python +y = a.x +``` + +Ici, `y` est l'attribut `x` de l'objet `a`. + +# Attributs - 2 + +Les attributs peuvent être des fonctions: + +```python +func = a.x +func(10) +``` + +Ici, on crée une variable `func` qui prend la valeur de l'attribut `x` dans `a`, puis +on l'appelle dans la ligne suivante. + +Le code suivant fait exactement la même chose, mais avec une ligne de moins: + +```python +a.x(10) +``` + +# Attributs - 3 + +On a déjà vu des attributs, quand on a utilisé des `modules` + +```python +import random + +nombre_au_hasard = random.randint(0, 10) +``` + +Ici, `random` est un module, et `randint` est un *attribut* du module `random`. Il se trouve +que cet attribut est un fonction qu'on peut appeler avec deux arguments. + +On reviendra sur les modules dans un prochain chapitre. + +# Attributs - 4 + +On peut *rajouter* des attributs à n'importe quel objet, en utilisant l'*assignation*: + +```python +>>> mon_instance = MonObjet() + +# Création de l'attribut `x dans `mon_instance` +>>> mon_instance.x = 42 + +# Accés à l'attribut `x` dans `mon_instance` +>>> mon_instance.mon_attribut +42 +``` + +# Méthodes - définition + +On peut aussi mettre des *méthodes* dans des classes. + +On utilise `def`, comme pour les fonctions, mais les méthodes *doivent* avoir au +moins un argument appelé `self`, et être à l'intérieur du bloc de la classe: + +```python +class MonObjet: + # le bloc 'def' est a l'intérieur du bloc + # de la classe + def ma_méthode(self): + return 42 +``` + +# Méthodes - appel + +Une méthode ne peut être appelée que depuis une *instance* de +l'objet: + +```python +class MonObjet: + def ma_méthode(self): + return 42 +>>> ma_méthode() +Erreur + +>>> mon_instance = MonObjet() +>>> mon_instance.ma_méthode() +42 +``` + +Notez qu'on ne passe *pas* d'argument quand on apelle `ma_méthode` depuis l'instance de l'objet. + + +# Méthodes et attributs - 1 + +`self` *prend la valeur de l'instance courante* quand la méthode est appelée. + +On peut le voir en utilisant des attributs: + +```python +class MonObjet: + def affiche_attribut_x(self): + # Accès à l'attribut `x` dans `self` + print(self.x) + + +>>> mon_instance = MonObjet() +>>> mon_instance.x = 42 +>>> mon_instance.affiche_attribut_x() +42 +``` + +# Méthodes et attributs - 2 + +On peut aussi *créer* des attributs dans une méthode: + +```python +class MonObjet: + def crée_attribut_x(self): + self.x = 42 + def affiche_attribut_x(self): + print(self.x) + +>>> mon_instance = MonObjet() +>>> 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 et attributs - 3 + +Les méthodes peuveunt aussi prendre plusieurs arguments, en plus de `self` - mais `self` doit +toujours être le premier argument. + +Par example, pour créer un attribut avec une certaine valeur: + + +```python +class MonObjet + def crée_attribut_x(self, valeur_de_x): + self.x = valeur_de_x + + def affiche_attribut_x(self); + print(self.x) + +>>> mon_instance = MonObjet() +>>> mon_instance.crée_attribut_x(42) +>>> mon_instance.affiche_attribut_x() +42 +``` + +# Méthodes appelant d'autres méthodes - 1 + +Comme les méthodes sont *aussi* des attributs, les méthodes d'un objet peuvent s'appeler +les unes les autres: + +```python +class MonObjet: + 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") +``` + +# Méthodes appelant d'autres méthodes - 2 + +```python +>>> mon_instance = MonObjet() +>>> 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 +``` + +# Une méthode spéciale + +Si vous définissez une méthode `__init__`, celle-ci est appelée *automatiquement* +quand l'objet est construit. + +On dit que c'est une méthode "magique" parce qu'elle fait quelque chose _sans_ qu'on +l'appelle explicitement. + +# \_\_init\_\_ + +On utilise souvent `__init__` pour créer des attributs + + +```python +class MonObjet: + def __init__(self): + self.x = 1 + self.y = 2 + +>>> mon_instance = MonObjet() + +# __init__ est appelée automatiquement! +>>> mon_instance.x +1 +>>> mon_instance.y +2 +``` + +# \_\_init\_\_ - 2 + +On prend souvent les *valeurs* des attributs à créer en paramètres de la méthode `__init__ `. + +```python +class MonObjet: + def __init__(self, x, y): + self.x = x + self.y = y +``` + +Dans ce cas, les paramètres des `__init__` apparaissent à l'intérieur des parenthèses après le +nom de la classe: + +``` +>>> mon_instance = MonObjet(3, 4) +>>> mon_instance.x +3 +>>> mon_instance.y +4 +``` + +*Pour cette raison, `__init__` est souvent appelé le _constructeur_ de la classe.* + +# Récapitulatif + +* Classe: plan de construction +* Objet: ce qu'on crée avec le plan +* Attribut: variable dans un objet +* Instance: objet issue d'une classe +* Méthode: fonction dans une classe (qui prend `self` en premier argument) +* `__init__`: méthode magique appelée automatiquement pendant l'instaciation