Dimitri Merejkowsky 5 лет назад
Родитель
Сommit
429df44426
1 измененных файлов: 252 добавлений и 0 удалений
  1. +252
    -0
      sessions/python-06.md

+ 252
- 0
sessions/python-06.md Просмотреть файл

@@ -0,0 +1,252 @@
% Programmation avec Python (chapitre 6)
% Dimitri Merejkowsky


#

\center \huge Les classes

# Paradigmes

Une façon d'envisager le code.
Pour l'instant on n'a vu que le paradigme *procédural* (ou (impératif).

Il y en a plein d'autres! (*fonctionnel* notamment, dont on parlera un jour)

# Détails du procédural

* des types simples (entiers, booléens)
* des structures de données (dictionnaires, listes ...)
* des fonctions qui manipulent des types simples ou des structures
* les fonctions sont appelées les unes après les autres

Aujourd'hui on va parler de *l'orienté objet*.

# Un petit détour

Un nouveau built-in: `id()`

L'adresse de l'objet pointé par la variable:

```
>>> a = 42532
>>> id(a)
94295009035968
>>> b = a
>>> id(b) # même objet
94295009035968
>>> c = 42532 # objet différent, même valeur
>>> id(c)
```

# Orienté objet - 1ère 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

OOP en Anglais (ou juste OO)

# Orienté objet - 2è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

# 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, c'est le mot-clé `class` et un nom.

```python
class MyObject:
pas
```

La classe est le plan de construction de notre objet.

# Créons des objets

```python
>>> object_1 = MyObject()
>>> object_2 = MyObject()
```

Python ne sait rien de l'objet à part son adresse on mémoire et son nom:

```python
print(object_1)
<__main__.MyObject at 0x7f52c831e2b0>
```

On appelle `object_1` et `object_2` des *instances* de la classe `MyObject`.

# Méthodes

Une fonction dans une classe

```
class MyObject:
def my_method(the_object):
print("hello", the_object)
```

C'est tout!

# Méthodes - 2

La méthode n'existe pas en dehors de la classe (souvenez vous des cellules !)

```
>>> my_method()
NameError
>>> object = MyObject()
>>> object.my_method()
Hello, <MyObject at 0x7f52c9f6d6d8>
```

Notez que `my_method` a pris en premier argument ce qu'il y avait *à gauche* du point:

D'ailleurs, ce code fonctionne aussi et retourne *la même chose*:

```
>>> MyObject.my_method(object)
Hello, <MyObject at 0x7f52c9f6d6d8>
```

# Méthodes - 3

Il *faut* passer l'objet en cours en paramètre:

```python
class MyObject:
def broken():
print("You cannot call me!")
```

```python
>>> o = MyObject()
>>> o.broken()
TypeError: broken() takes 0 positional arguments but 1 was given
```

# Conventions

* Les classes sont en CamelCase
* Tout le reste (méthodes, etc...) en snake_case
* L'objet en cours s'appelle **toujours** `self`


```python
class MyObject:
def my_method(self):
print("hello", self)
```

# Attributs

* Des variables dans un objet.
* On peut ajouter un attribut quand on veut à qui on veut, et toujours avec le
point au milieu:

```python
>>> object = MyObject()
>>> object.attribute # ici l'attribut n'existe pas
AttributError
>>> object.attribute = 42 # maintenant oui
>>> object.attribute
42
```

# Attributs dans les méthodes

Avec `self`, bien sûr:

```python
class MyObject:
def print_attribute(self):
print(self.attribute)

def change_attribute(self, new_value)
self.attribute = new_value
```

# Accéder aux attributs

```python
>>> object = MyObject()
>>> object.print_attribute() # ici l'attribut n'existe pas
AttributError
>>> object.attribute = 42
>>> object.print_attribute() # ça marche
42
>>> object.change_attribute(43)
>>> object.attribute
43
```

# Initialisation des attributs

Avec `__init__`:

* méthode "spéciale"
* appelée automatiquement
* notez les deux underscores avant et après ('dunder' en Anglais)

```python
class MyObject:
def __init__(self):
self.attribute = 42
```

```python
>>> object = MyObject()
>>> object.attribute
42
```

# Construire des objets différents

`__init__()` et `MyObject()` sont des appels de fonctions comme les autres

```python
class Car:
def __init__(self, color_to_use="black"):
self.color = color_to_use

>>> ford = Car()
>>> ford.color
"black"
>>> ferrari = Car(color_to_use="red")
>>> ferrari.color
"red"
```

# Notes

En vrai, on nomme souvent les paramètres du constructeur et les attributes de la même façon.

```python
class Car:
def __init__(self, color="black"):
self.color = color
```

# Récapitulatif

* Classe: plan de construction
* Object: ce qu'on crée avec le plan
* Instance: objet issue d'une classe
* Méthode: fonction dans une classe (qui prend `self` en premier argument)
* Attribut: variable dans un objet