CPGE Oujda                                                                                                                                                    Spé

Introduction à la Programmation Orientée Objet

Nous avons vu plusieurs types de base en Python (int pour les entiers, float pour les flottants, str pour les chaînes de caractères, etc.). La notion de classe va en quelque sorte nous permettre de généraliser la notion de “type” afin de créer de nouvelles structures de données.

Une classe définit des attributs et des méthodes. Par exemple, imaginons une classe Voiture qui servira à créer des objets qui sont des voitures. Cette classe va pouvoir définir un attribut couleur, un attribut vitesse, etc. Ces attributs correspondent à des propriétés qui peuvent exister pour une voiture. La classe Voiture pourra également définir une méthode rouler(). Une méthode correspond en quelque sorte à une action, ici l’action de rouler peut être réalisée pour une voiture. Si on imagine une classe Avion, elle pourra définir une méthode voler(). Elle pourra aussi définir une méthode rouler(). Par contre, la classeVoiture n’aura pas de méthode voler() car une voiture ne peut pas voler. De même, la classe Avion pourra avoir un attributaltitude mais ce ne sera pas le cas pour la classe Voiture.

Après avoir présenté la notion de classe, nous allons voir la notion d’objet. On dit qu’un objet est une instance de classe. Si on revient à la classe Voiture, nous pourrons avoir plusieurs voitures qui seront chacune des instances bien distinctes. Par exemple, la voiture de Mohamed, qui est de couleur rouge avec une vitesse de 30 km/h, est une instance de la classe Voiture, c’est un objet. De même, la voiture de Brahim, qui est de couleur grise avec une vitesse de 50 km/h, est un autre objet. Nous pouvons donc avoir plusieurs objets pour une même classe, en particulier ici deux objets (autrement dit : deux instances de la même classe). Chacun des objets a des valeurs qui lui sont propres pour les attributs.

Les notions de classe et d’objet

Définition d’une classe Point

Voici comment définir une classe appelée ici Point.

class Point:

    "Definition d'un point geometrique"

Par convention en Python, le nom identifiant une classe (qu’on appelle aussi son identifiant) débute par une majuscule. Ici Point débute par un P majuscule.

Création d’un objet de type Point

Point()

Ceci crée un objet de type Point. En POO, on dit que l’on crée une instance de la classe Point.

Affectation à une variable de la référence à un objet

Nous venons de définir une classe Point. Nous pouvons dès à présent nous en servir pour créer des objets de ce type, par instanciation. Créons par exemple un nouvel objet et mettons la référence à cet objet dans la variable p :

>>> p = Point()

Nous pouvons dès à présent effectuer quelques manipulations élémentaires avec notre nouvel objet dont la référence est dans p.

Exemple

>>> print(p)

<__main__.Point instance at 0x012CAF30>

Le message renvoyé par Python indique que p contient une référence à une instance de la classe Point, qui est définie elle-même au niveau principal du programme. Elle est située dans un emplacement bien déterminé de la mémoire vive, dont l’adresse apparaît ici en notation hexadécimale.

Exemple avec deux objets

a = Point()

b = Point()

On fait bien ici la distinction entre classe et objet. Ici nous avons une seule classe Point, et deux objets de type Point.

Définition des attributs

class Point:

    "Definition d'un point geometrique"                  _images/2014-11-22_13-30-47.png

p = Point()

p.x = 1

p.y = 2

print("p : x =", p.x, "y =", p.y)                                                                                                            p : x = 1 y = 2

L’objet dont la référence est dans p possède deux attributs : x et y.

La syntaxe pour accéder à un attribut est la suivante : on va utiliser la variable qui contient la référence à l’objet et on va mettre un point . puis le nom de l’attribut.

Exemple

class Point:

    "Definition d'un point geometrique"

a = Point()                                             _images/2014-11-22_09-47-40.png

a.x = 1

a.y = 2

b = Point()

b.x = 3

b.y = 4                                                                                

print("a : x =", a.x, "y =", a.y)                                                                                            

print("b : x =", b.x, "y =", b.y)                                                                                                          

Exécuter

On a 2 instances de la classe Point, c’est-à-dire 2 objets de type Point. Pour chacun d’eux, les attributs prennent des valeurs qui sont propres à l’instance.

Les variables x et y que nous avons ainsi définies en les liant d'emblée à a , sont désormais des attributs de l'objet a. On peut également les appeler des variables d'instance.

Distinction entre variable et objet

L’exemple suivant montre bien la distinction entre variable et objet :

class Point:

    "Definition d'un point geometrique"

a = Point()                              _images/2014-11-22_09-56-48.png

a.x = 1

a.y = 2

b = a

print("a : x =", a.x, "y =", a.y)

print("b : x =", b.x, "y =", b.y)

a.x = 3

a.y = 4

print("a : x =", a.x, "y =", a.y)

print("b : x =", b.x, "y =", b.y)

Ici les variables a et b font référence au même objet. En effet, lors de l’affectation b = a, on met dans la variable b la référence contenue dans la variable a. Par conséquent, toute modification des valeurs des attributs de l’objet dont la référence est contenue dans a entraîne une modification pour b.

Définition des méthodes

class Point:

    def deplace(self, dx, dy):

        self.x = self.x + dx

        self.y = self.y + dy

Cette classe possède une méthode : deplace().

Pour définir une méthode, il faut :

  1. indiquer son nom (ici deplace()).
  2. indiquer les arguments entre des parenthèses. Le premier argument d’une méthode doit être self.

Pour accéder aux méthodes d’un objet, on indique :

le nom de la variable qui fait référence à cet objet ,un point et le nom de la méthode

a.deplace(3, 5)

NB : Lors de l’appel de la méthode, le paramètre self n’est pas utilisé et la valeur qu’il prend est la référence à l’objet. Il y a donc toujours un paramètre de moins que lors de la définition de la méthode.

Exemple

class Point:

    def deplace(self, dx, dy):

        self.x = self.x + dx

        self.y = self.y + dy

a = Point()

a.x = 1

a.y = 2

print("a : x =", a.x, "y =", a.y)

a.deplace(3, 5)

print("a : x =", a.x, "y =", a.y)

La notion de constructeur

Si lors de la création d’un objet nous voulons qu’un certain nombre d’actions soit réalisées (par exemple une initialisation), nous pouvons utiliser un constructeur.

Un constructeur n’est rien d’autre qu’une méthode, sans valeur de retour, qui porte un nom imposé par le langage Python :__init__(). Ce nom est constitué de init entouré avant et après par __ (deux fois le symbole underscore _, qui est le tiret sur la touche 8). Cette méthode sera appelée lors de la création de l’objet. Le constructeur peut disposer d’un nombre quelconque de paramètres, éventuellement aucun.

Exemple sans paramètre

class Point:

    def __init__(self):

        self.x = 0

        self.y = 0

a = Point()

print("a : x =", a.x, "y =", a.y)

a.x = 1

a.y = 2

print("a : x =", a.x, "y =", a.y)Exécuter

Dans cet exemple, nous avons pu définir des valeurs par défaut pour les attributs grâce au constructeur.

Exemple avec paramètres

class Point:

    def __init__(self, abs, ord):

        self.x = abs

        self.y = ord

a = Point(1, 2)

print("a : x =", a.x, "y =", a.y)

Exécuter

Autre exemple avec paramètres

Dans l’exemple suivant, on utilise les mêmes noms pour les paramètres du constructeur et les attributs. Ceci ne pose pas de problème car ces variables ne sont pas dans le même espace de noms. Les paramètres du constructeur sont des variables locales, comme c’est habituellement le cas pour une fonction. Les attributs de l’objet sont eux dans l’espace de noms de l’instance. Les attributs se distinguent facilement car ils ont self devant.

class Point:

    def __init__(self, x, y):

        self.x = x

        self.y = y

a = Point(1, 2)

print("a : x =", a.x, "y =", a.y)

La notion d’encapsulation

Le concept d’encapsulation est un concept très utile de la POO. Il permet en particulier d’éviter une modification par erreur des données d’un objet. En effet, il n’est alors pas possible d’agir directement sur les données d’un objet ; il est nécessaire de passer par ses méthodes qui jouent le rôle d’interface obligatoire.

Définition d’attributs privés (attribut d’instance)

On réalise la protection des attributs de notre classe Point grâce à l’utilisation d’attributs privées. Pour avoir des attributs privés, leur nom doit débuter par __ (deux fois le symbole underscore _, qui est le tiret sur la touche 8).

class Point:

    def __init__(self, x, y):

        self.__x = x

        self.__y = y

Il n’est alors plus possible de faire appel aux attributs __x et __y depuis l’extérieur de la classe Point.

>>> p = Point(1, 2)

>>> p.__x

Traceback (most recent call last):

  File "<pyshell#9>", line 1, in    p.__x      AttributeError: Point instance has no attribute '__x'

Il faut donc disposer de méthodes qui vont permettre par exemple de modifier ou d’afficher les informations associées à ces variables.

class Point:

    def __init__(self, x, y):

        self.__x = x

        self.__y = y

    def deplace(self, dx, dy):

        self.__x = self.__x + dx

        self.__y = self.__y + dy

    def affiche(self):

        print("abscisse =", self.__x, "ordonnee =", self.__y)

a = Point(2, 4)

a.affiche()

a.deplace(1, 3)

a.affiche()

Attributs de classe

Exemple :

class A:

    nb = 0

    def __init__(self, x):

        print("creation objet de type A")

        self.x = x

        A.nb = A.nb + 1

print("A : nb = ", A.nb)

print("Partie 1")

a = A(3)

print("A : nb = ", A.nb)

print("a : x = ", a.x, " nb = ", a.nb)

print("Partie 2")

b = A(6)

print("A : nb = ", A.nb)

print("a : x = ", a.x, " nb = ", a.nb)

print("b : x = ", b.x, " nb = ", b.nb)

c = A(8)

print("Partie 3")

print("A : nb = ", A.nb)

print("a : x = ", a.x, " nb = ", a.nb)

print("b : x = ", b.x, " nb = ", b.nb)

print("c : x = ", c.x, " nb = ", c.nb)

Exercice

Définir une classe Point3D qui sera analogue à la classe Point mais pour des points dans l’espace à 3 dimensions. Créer deux objets de type Point3D qui seront référencés par les variables a3D et b3D. Initialiser ces points et afficher leurs coordonnées xy,z.