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