• 6 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 08/11/2019

Créez votre première Zone !

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Nous avons les agents, la position de chaque agent et globalement la possibilité de calculer une position. Bien bien ! Il nous faut maintenant créer le plateau de jeu, donc l'ensemble de zones qui constituent notre monde.

La classe Zone

Créons la classe Zone qui a trois attributs : la position de son coin inférieur gauche, la position de son coin supérieur droit et ses habitants. 

Lorsque nous créerons chaque zone, nous déterminerons sa position et disons que, par défaut, la zone est vide.

class Zone:
    def __init__(self, corner1, corner2):
        self.corner1 = corner1
        self.corner2 = corner2
        self.inhabitants = 0

Parfait. Maintenant, comment allons-nous créer toutes les zones qui constituent le monde ? Nous allons le voir comme un quadrillage qui est composé de plusieurs lignes verticales et horizontales.

Les attributs de classe

Si nous reprenons notre jeu de bataille navale, nous voyons que nous avons plusieurs lignes. Une ligne a une abscisse minimale, une abscisse maximale et un intervalle distinguant chaque zone minimale de jeu.

Autrement dit, toujours dans le jeu, nous avons 9 zones comprises entre 0 et 9 avec un intervalle de 1 pour cette première ligne. Nous allons utiliser la même logique dans notre grille mais pas les mêmes valeurs, puisque la longitude est comprise entre -180 et 180 degrés et que la latitude, elle, est comprise entre -90 et 90 degrés.

Pour créer la première ligne de notre grille, nous devons donc définir certaines variables qui, a priori, ne changeront pas. Nous voulons qu'elles soient associées à la classe et non pas aux instances. En effet, si nous changeons l'abscisse minimale de nos zones, nous voulons le faire pour toutes les instances en une fois. Nous pouvons raisonnablement nous dire que le champ d'action de ces variables sera plus large que celui des attributs d'instance.

Nous appelons ces variables des attributs de classe car elles appartiennent à la classe dans son ensemble, et non à l'instance. C'est notre zone de manière générale qui a une latitude minimale et une latitude maximale, et non l'instance !

 

Ajouter un attribut de classe

Par convention, un attribut de classe s'indique en majuscules, avant les méthodes :

class Zone:
    
    MIN_LONGITUDE_DEGREES = -180

    def __init__(self, corner1, corner2):
        self.corner1 = corner1
        self.corner2 = corner2
        self.inhabitants = 0

Vous pouvez par la suite y accéder en écrivant MaClasse.MON_ATTRIBUT_DE_CLASSE. Exemple :

print(Zone.MIN_LONGITUDE_DEGREES)

Indiquons tous les attributs dont nous aurons besoin pour notre première ligne :

class Zone:

    MIN_LONGITUDE_DEGREES = -180
    MAX_LONGITUDE_DEGREES = 180
    WIDTH_DEGREES = 1 # degrees of longitude

Nous allons ensuite créer une méthode qui va initialiser la grille, en commençant par la longitude.

def initialize_zones(self):

 

Créer les lignes avec la longitude

Nous créons une première boucle qui crée une zone pour chaque nombre compris entre MIN_LONGITUDE_DEGREES et MAX_LONGITUDE_DEGREE.
La méthode range() permet justement de créer une liste à partir d'une valeur minimale, d'une valeur maximale et d'un intervalle. range(minimal_value, maximal_value, added_value)

class Zone
    ...
    def initialize_zones(self):
        for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
            # zone = Zone(bottom_left_corner, top_right_corner)

Chaque instance de type Zone prend en paramètre la position de son coin inférieur gauche et la position de son coin supérieur droit. Dans notre cas, il s'agit de la toute première ligne. La latitude est donc toujours égale à 1 ! Quant à la longitude de départ, nous y avons déjà accès dans notre boucle :

class Zone
    ...
    def initialize_zones(self):
        for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
            bottom_left_corner = Position(longitude, 1)

Comment calculer la position du coin supérieur droit ? En ajoutant un intervalle ! Nous l'avons d'ailleurs déjà stocké dans l'attribut de classe WIDTH_DEGREE : 

class Zone    
    def initialize_zones(self):
        for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
            bottom_left_corner = Position(longitude, 1)
            top_right_corner = Position(longitude + self.WIDTH_DEGREES)

Néanmoins, il nous manque l'intervalle utilisé pour la latitude. Ajoutons-le :

class Zone    
    MIN_LONGITUDE_DEGREES = -180
    MAX_LONGITUDE_DEGREES = 180
    WIDTH_DEGREES = 1 # degrees of longitude
    HEIGHT_DEGREES = 1 # degrees of latitude
    ...

Nous pouvons désormais calculer également la latitude du coin supérieur droit et créer la zone correspondante : 

class Zone
    ...
    def initialize_zones(self):
        for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
            bottom_left_corner = Position(longitude, 1)
            top_right_corner = Position(longitude + self.WIDTH_DEGREES, 1 + self.HEIGHT_DEGREES)
            zone = Zone(bottom_left_corner, top_right_corner)

Paaaaarfait ! Nous allons ensuite créer une seconde boucle, sur le même principe, pour effectuer la même opération mais au niveau de la latitude ! Une boucle à l'intérieur d'une boucle, comme dans Inception :)

Créer les colonnes avec la latitude

Ajoutons les attributs de classe :

class Zone
...
    MIN_LATITUDE_DEGREES = -90
    MAX_LATITUDE_DEGREES = 90
    WIDTH_DEGREES = 1 # degrees of longitude
    HEIGHT_DEGREES = 1 # degrees of latitude

 

Enfin ajoutons une autre boucle concernant la latitude : 

class Zone
    ...
    def initialize_zones(self):
        for latitude in range (self.MIN_LATITUDE_DEGREES, self.MAX_LATITUDE_DEGREES, self.HEIGHT_DEGREES):
            for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
                bottom_left_corner = Position(longitude, latitude)
                top_right_corner = Position(longitude + self.WIDTH_DEGREES, latitude + self.HEIGHT_DEGREES)
                zone = Zone(bottom_left_corner, top_right_corner)

YEAH !! Si nous lançons notre programme, nos remarquons que toutes les zones se créent ! :) 

Toutes les zones de notre grille

Pourquoi avons-nous créé cette grille ? Pour positionner nos habitants à l'intérieur. Il nous faut donc un moyen de parcourir toutes les zones, d'une manière ou d'une autre, afin de trouver la zone d'habitation de chaque agent. Or pour le moment, nous ne stockons les instances nulle part. Elles sont créées et seul l'ordinateur sait où elles sont.

Agréger toutes les zones

Nous allons donc créer un nouvel attribut de classe pour stocker chaque nouvelle zone qui est créée.

class Zone:

    ZONES = []
    ... 

Enfin, à l'intérieur de notre méthode qui initialise les zones, nous allons ajouter une à une chaque zone à notre liste ZONES.

class Zone:
    ...
    
    def initialize_zones(self):
        ...
        self.ZONES.append(zone)

Afin de connaître combien de zones ont été créées, j'ajoute un print() à la fin :

class Zone:
    ...
    
    def initialize_zones(self):
        for latitude in range (self.MIN_LATITUDE_DEGREES, self.MAX_LATITUDE_DEGREES, self.HEIGHT_DEGREES):
            for longitude in range(self.MIN_LONGITUDE_DEGREES, self.MAX_LONGITUDE_DEGREES, self.WIDTH_DEGREES):
                bottom_left_corner = Position(longitude, latitude)
                top_right_corner = Position(longitude + self.WIDTH_DEGREES, latitude + self.HEIGHT_DEGREES)
                zone = Zone(bottom_left_corner, top_right_corner)
                self.ZONES.append(zone)
        print(len(self.ZONES))

 

Les méthodes de classe

Exécutons notre script afin de vérifier que tout fonctionne...

...

Mille milliards de mille sabords ! Rien ne se passe ! Pourquoi donc ?

Réfléchissons un peu... Ah, mais bien sûr ! À aucun moment je n'exécute la méthode. Pour l'instant je l'ai juste définie ! Forcément, cela ne risque pas de fonctionner... 

J'aimerais pouvoir lancer ma méthode maintenant ! Mais si j'essaie de la lancer, je suis prise moi-même dans une boucle infinie. Le seul moyen que nous connaissions pour lancer une méthode, jusqu'à maintenant, est de créer une instance et de l'utiliser pour exécuter la méthode. Comme ceci :

zone = Zone(1, 1)
zone.initialize_zones()

Mais... Comment lancer une méthode sur une instance alors que cette même méthode est celle qui, justement, est censée les créer ? Aaaaah !

Il faudrait une méthode qui soit globale, au niveau de la classe, et non de l'instance. En fait nous l'avons déjà fait pour les attributs d'instance et de classe ! Alors, comment le faire pour les méthodes ? Vous ajoutez  @classmethod  juste avant.

class Zone:
    ...
    
    @classmethod
    def initialize_zones(self):
        ...

Bien. Étant donné que nous ne sommes plus au niveau de l'instance mais au niveau de la classe, nous allons remplacer self par cls (afin de ne pas confondre).

Nous allons donc remplacer par cls :

class Zone:
    
    @classmethod
    def initialize_zones(cls):
        for latitude in range (cls.MIN_LATITUDE_DEGREES, cls.MAX_LATITUDE_DEGREES, cls.HEIGHT_DEGREES):
            for longitude in range(cls.MIN_LONGITUDE_DEGREES, cls.MAX_LONGITUDE_DEGREES, cls.WIDTH_DEGREES):
                bottom_left_corner = Position(longitude, latitude)
                top_right_corner = Position(longitude + cls.WIDTH_DEGREES, latitude + cls.HEIGHT_DEGREES)
                zone = Zone(bottom_left_corner, top_right_corner)
                cls.ZONES.append(zone)
        print(len(cls.ZONES))

Nous pouvons désormais l'exécuter hors de la classe ainsi :  MaClasse.MaMethodeDeClasse() 

Zone.initialize_zones()

Bravo bravo ! Nous avons notre grille ! Nous allons dans le prochain chapitre ajouter les habitants.

Vous souhaitez en savoir plus sur les méthodes de classe et découvrir une autre manière de les créer ? Je vous conseille le chapitre Première approche des classes du cours Apprenez à programmer en Python de Vincent le Goff. 

Code de ce chapitre

Retrouvez le code de ce chapitre en cliquant ici : https://github.com/OpenClassrooms-Student-Center/la_poo_avec_python/tree/04_class_methods

 

Exemple de certificat de réussite
Exemple de certificat de réussite