Un bref aperçu des classes#

Links: notebook, html, python, slides, GitHub

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.

from jyquickhelper import add_notebook_menu
add_notebook_menu()

Une station de métro#

Une station de métro est définie par son nom et sa position. Un dictionnairre peut suffire.

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…

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.

station.name
'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#

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)
0.6928550943713419

La même écriture avec des classes.

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)
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.

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)
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.

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)
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.

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
0.6928550943713419