Browse Source

Première version du chapitre 5

master
Dimitri Merejkowsky 4 years ago
parent
commit
42725f1d37
2 changed files with 370 additions and 1 deletions
  1. +1
    -1
      saison-2/sessions/Makefile
  2. +369
    -0
      saison-2/sessions/python-S02-E05.md

+ 1
- 1
saison-2/sessions/Makefile View File

@@ -1,4 +1,4 @@
all: python-S02-E04.pdf
all: python-S02-E05.pdf

%.pdf: %.md
pandoc --pdf-engine=xelatex -t beamer $< -o $@

+ 369
- 0
saison-2/sessions/python-S02-E05.md View File

@@ -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 `<objet>.<attribut>`:

```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