Python: Classe

From Wiki Cours
Jump to navigation Jump to search

<--Sommaire

Déclaration

Une classe définit un nouveau type de donnée. Ce type comporte un nom qui définit un espace de nommage à l'intérieur de son bloc de définition. Ce type peut contenir des attributs ou membres (pour les variables) et des méthodes (pour les fonctions).

La syntaxe pour déclarer une classe est la suivante

class A:                      # déclaration du nom
    """première classe"""     # documentation
    data = 2                  # attribut
dir(A)

Une classe peut déjà permettre de structurer les données. On parle d'encapsulation des données. La fonction dir() permet de faire afficher le contenu de la classe. Pour accéder aux membres de la classe, il faut utiliser l'opérateur .

print(A.data)

Une fois une classe déclarée, contrairement aux langages à typage statique, il est toujours possible en Python de déclarer de nouveaux attributs.

A.b = "blabla"
dir(A)

On voit que l'attribut b a été rajouté à la déclaration de la classe.

En Python, tout est objet, les types de base, les fonctions, les modules, etc... En appliquant dir() sur n'importe quel objet ou nom, on peut voir ses attributs et ses méthodes.

Instantiation

Une classe est utile pour créer des objets ou instances qui sont des variables définies avec la classe créée. La déclaration, ou instantiation, suit la même syntaxe que pour les types habituellement rencontrés, avec les parenthèses pour appeler la méthode qui crée l'objet (voir ci-après):

a = A() # l'objet a est créé avec le type A
print(a.data)
a.data = 4322
print(a.data, A.data)
A.data = -2
print(a.data, A.data)

En python, les objets et la classe elle-même sont des objets. On peut modifier indépendamment le contenu de chacun comme dans l'exemple ci-dessus. On accède aux membres des objets avec l'opérateur ..

Il est possible en python de rajouter des attributs à une instance qui ne soit pas initialement dans la classe. On parle alors d'attributs d'instance au lieu d'attributs de classe qui sont ceux définis au niveau de la classe et donc partagés par toutes les instances créés à partir de celle-ci:

a.extra = "que pour a"
print(dir(a), dir(A))

On peut rajouter un attribut à toutes les instances de la classe en la rajoutant à la définition même de la classe:

A.pourtous = "!!"
print(dir(A))
print(dir(a))

Le code ci-dessous permet de distinguer les attributs de classe, les attributs d'instance et une variable globale ayant le même nom:

class A:
    data = 2   # attribut de classe
    def __init__(self):
        self.data = 3  # attribut d'instance

data = 1 # variable globale
a = A()
print(data, A.data, a.data)

Déclaration des méthodes

La déclaration des méthodes se fait le plus souvent à l'intérieur du corps de déclaration de la classe. Le mot-clé self fait référence à l'instance qui sera créée. Ainsi, self.data correspond à l'attribut de l'instance. Il est nécessaire de l'utiliser car si l'on écrit data seul cela correspondrait à une variable locale de la fonction. De même, self doit toujours apparaître en premier argument des méthodes pour que celles-ci puissent être appelées par les instances de la classe. Typiquement, on aura donc les déclarations:

class A:
    def __init__(self,d=1):
        self.data = d
    def change(self):
        self.data += 2
    def multiplier(self,n):
        for i in range(n):
            self.change()

On accède aux méthodes de la même manière que pour les attributs. L'argument self n'a pas à être redonné. Lorsqu'une méthode appelle une autre méthode (fonction multiplier() qui appelle change()), il faut utiliser la syntaxe self.methode() pour que cette méthode soit bien appelée par l'instance créée.

a = A()
a.change()
a.multiplier(3)
print(a.data)

La méthode __init__() ci-dessus est une méthode spéciale appelée initialisateur. C'est elle qui définit ce qu'il se passe lors de l’instanciation des objets. Il existe une version par défaut mais on peut la réécrire et lui donner un certain nombre d'arguments comme toute fonction.

a = A()  # initialisation avec d=1 par défaut
a = A(4) # initialisation avec d=4
print(a.data)

Il est possible de définir une nouvelle méthode en dehors du corps principal de déclaration de la classe en définissant une fonction puis en l'associant à une méthode de la classe comme un nouvel attribut:

def reset(self):
    self.data = 0

A.reset = reset
dir(A)
a.reset()
print(a.data)

On pollue cependant l'espace de nom principal en faisant cela. Il est plus utile d'utiliser le mécanisme d'héritage pour découper les structures de classe ou ne pas hésiter à avoir une longue déclaration de classe.