.. _2022classesrst: ========================== Un bref aperçu des classes ========================== .. only:: html **Links:** :download:`notebook <2022_classes.ipynb>`, :downloadlink:`html <2022_classes2html.html>`, :download:`python <2022_classes.py>`, :downloadlink:`slides <2022_classes.slides.html>`, :githublink:`GitHub|_doc/notebooks/td1a_home/2022_classes.ipynb|*` Les classes ou la programmation objet est une façon différente d’écrire et d’organiser un programme informatique. Cela ne permet rien de plus que les fonctions mais ça permet de le faire souvent de façon plus élégante. .. code:: ipython3 from jyquickhelper import add_notebook_menu add_notebook_menu() .. contents:: :local: Une station de métro -------------------- Une station de métro est définie par son nom et sa position. Un dictionnairre peut suffire. .. code:: ipython3 station = {'name': 'Charles Michels', 'lat': 48.846651, 'lng': 2.285811} L’inconvénient de cette écriture est qu’il faut toujours bien orthographier le nom des clés du dictionnaire. La moindre erreur empêche le programme de fonctionner. La seconde écriture avec des classes ne simplifie pas la tâche à première vue. Mais… .. code:: ipython3 class Station: def __init__(self, name, lat, lng): self.name = name self.lng = lng self.lat = lat station = Station("Charles Michels", 48.846651, 2.285811) Lorsqu’on écrit ce qui suit, l’autocomplétion du notebook montre les différentes possibilités. .. code:: ipython3 station.name .. parsed-literal:: 'Charles Michels' Les classes permettent de définir de nouveau type de données. Ici, une station, avec trois attributs, ``name``, ``lng``, ``lat``. Une distance ------------ .. code:: ipython3 import math def distance_haversine(s1, s2): radius = 6371 lat1 = s1['lat'] lat2 = s2['lat'] lng1 = s1['lng'] lng2 = s2['lng'] dlat = math.radians(lat2 - lat1) dlon = math.radians(lng2 - lng1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d station1 = {'name': 'Charles Michels', 'lat': 48.846651, 'lng': 2.285811} station2 = {'name': 'Emile Zola', 'lat': 48.847030, 'lng': 2.295262} distance_haversine(station1, station2) .. parsed-literal:: 0.6928550943713419 La même écriture avec des classes. .. code:: ipython3 def distance_haversine(s1, s2): radius = 6371 lat1 = s1.lat lat2 = s2.lat lng1 = s1.lng lng2 = s2.lng dlat = math.radians(lat2 - lat1) dlon = math.radians(lng2 - lng1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d station1 = Station("Charles Michels", 48.846651, 2.285811) station2 = Station("Emile Zola", 48.847030, 2.295262) distance_haversine(station1, station2) .. parsed-literal:: 0.6928550943713419 Méthode ------- Et comme cette fonction ne s’applique qu’aux stations de métro, on peut la définir en tant que fonction appartenant à la classe ou **méthode**. .. code:: ipython3 class Station: def __init__(self, name, lat, lng): self.name = name self.lng = lng self.lat = lat def distance_haversine(s1, s2): radius = 6371 lat1 = s1.lat lat2 = s2.lat lng1 = s1.lng lng2 = s2.lng dlat = math.radians(lat2 - lat1) dlon = math.radians(lng2 - lng1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d station1 = Station("Charles Michels", 48.846651, 2.285811) station2 = Station("Emile Zola", 48.847030, 2.295262) station1.distance_haversine(station2) .. parsed-literal:: 0.6928550943713419 Une méthode de la classe ``Station`` prend toujours comme premier paramètre une variable de type ``Station`` (ou **instance**). On le distingue en l’appelant ``self``. En python, c’est une convention, pas une obligation mais l’écriture est plus rigide dans d’autres langages. .. code:: ipython3 class Station: def __init__(self, name, lat, lng): self.name = name self.lng = lng self.lat = lat def distance_haversine(self, s2): radius = 6371 lat1 = self.lat lat2 = s2.lat lng1 = self.lng lng2 = s2.lng dlat = math.radians(lat2 - lat1) dlon = math.radians(lng2 - lng1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d station1 = Station("Charles Michels", 48.846651, 2.285811) station2 = Station("Emile Zola", 48.847030, 2.295262) station1.distance_haversine(station2) .. parsed-literal:: 0.6928550943713419 Ca fait la même chose mais cela s’écrit différemment. Opérateurs ---------- Les classes permettent également de définir des opérations. .. code:: ipython3 class Station: def __init__(self, name, lat, lng): self.name = name self.lng = lng self.lat = lat def distance_haversine(self, s2): radius = 6371 lat1 = self.lat lat2 = s2.lat lng1 = self.lng lng2 = s2.lng dlat = math.radians(lat2 - lat1) dlon = math.radians(lng2 - lng1) a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon / 2) * math.sin(dlon / 2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d def __rshift__(self, s2): return self.distance_haversine(s2) station1 = Station("Charles Michels", 48.846651, 2.285811) station2 = Station("Emile Zola", 48.847030, 2.295262) station1 >> station2 .. parsed-literal:: 0.6928550943713419