Classes et POO - lis-lab.frClasses Python permet le paradigme Programmation Orienté Objet (POO)....

Preview:

Citation preview

Classes et POO

Classes

Python permet le paradigme Programmation Orienté Objet (POO).

Les objets groupent des données et des méthodes (fonctions) logiquement liées.

Par exemple, pour objets de type list

>>> nombres = [3, 1, 2]

>>> nombres.reverse()

>>> nombres.sort()

>>> nombres.pop()

Classes

Python permet le paradigme Programmation Orienté Objet (POO).

Les objets groupent des données et des méthodes (fonctions) logiquement liées.

Par exemple, pour objets de type list

>>> nombres = [3, 1, 2]

>>> nombres.reverse()

>>> nombres.sort()

>>> nombres.pop()

Données

Fonctions

Classes

Paradigme fonctionnel/procédural :

vec1 = (3, 4)

vec2 = (1, -3)

def longueur(v):

return math.sqrt(v[0]**2 + v[1]**2)

long1 = longueur(vec1)

long2 = longueur(vec2)

print(vec1[0]) # Affiche '3'

Classes

Paradigme fonctionnel/procédural :

vec1 = (3, 4)

vec2 = (1, -3)

def longueur(v):

return math.sqrt(v[0]**2 + v[1]**2)

long1 = longueur(vec1)

long2 = longueur(vec2)

print(vec1[0]) # Affiche '3'

Données

Fonctions

Classes

Paradigme OO : définir un nouveau type Vecteur pour grouper les données d'un vecteur et le fonction qui agissent dessus.

Vecteur

xy

longueur()

Classes

Paradigme OO : définir un nouveau type Vecteur pour grouper les données d'un vecteur et le fonction qui agissent dessus.

vec1 = Vecteur(3, 4) # création d'un objet Vecteur

vec2 = Vecteur(1, -3) # création d'un objet Vecteur

long1 = vec1.longueur()

long2 = vec2.longueur()

print(vec1.x) # affiche 3

Classes

Paradigme fonctionnel/procédural

chat1 = ('Felix', 5)

chat2 = ('Cléo', 7)

def affiche_age(c):

print('{} a {} ans'.format(c[0], c[1]))

affiche_age(chat1)

affiche_age(chat2)

Classes

Paradigme OO :

chat1 = Chat('Felix', 5)

chat2 = Chat('Cléo', 7)

chat1.affiche_age()

print(chat.nom)

Chat

nomage

affiche_age()

Classes

Ces nouveaux types s'appellent classes.

Une nouvelle classe est définie par le mot-clé class.

class NomDeLaClasse:

<instruction 1>

<instruction 2>

.

.

.

<instruction N>

Classes

La définition d'une classe :

class Vecteur:

'''Cette classe représente un vecteur.'''

def __init__(self, a, b):

self.x = a

self.y = b

def longueur(self):

return math.sqrt(self.x**2 + self.y**2)

Création d'instances de la classe = objets :

vec1 = Vecteur(3, 4) # appel de __init__(..., 3, 4)

# aucun argument pour 'self'

print(vec1.x) # Affiche '3'

Classes

class Vecteur:

'''Cette classe représente un vecteur.'''

def __init__(self, a, b):

self.x = a

self.y = b

def longueur(self):

return math.sqrt(self.x**2 + self.y**2)

Finalement, on peut appeler les méthodes sur l'objet :

long = Vecteur.longueur(vec1)

Syntaxe alternative, plus pratique (sans argument explicite pour self):

long = vec1.longueur()

Classes

class Chat:

'''Cette classe représente un chat.'''

def __init__(self, n, a):

self.nom = n

self.age = a

def affiche_age(self):

print('{} a {} ans'.format(self.nom, self.age))

def parle(self):

print('miaou')

monchat = Chat('Felix', 5)

monchat.affiche_age()

monchat.parle()

Classes

Deux syntaxe pour appeler les méthodes :● objet.methode() syntaxe courante (implicitement transformée dans

la deuxième)● Classe.methode(objet)

class Chat :

def parle(self):

print('miaou')

monchat = Chat()

monchat.parle() # Ces deux appels

Chat.parle(monchat) # sont équivalents

Classes

Quelques conventions.

● nom des classes : en « CamelCase »

Vecteur

PlanCartesien

Chat

MainWindow

● nom des objet : en minuscule (avec tirets bas)

vec = Vecteur(1, 2)

vec_longue = Vecteur(35,-43)

plan_cartesien = PlanCartesien()

chat1 = Chat('Felix', 5)

main_win = MainWindow()

Classes

Les méthodes ont toujours un premier argument qui représente, dans la méthode, l'objet = l'instance particulière.

Par convention, on l'appelle self.

...

def presente(self):

print('{} a {} ans'.format(self.nom, self.age))

def parle(self, n):

print('miaou ' * n)

def parle_beaucoup(self):

self.parle(10)

...

Classes

On peut définir des attributs pour les classes aussi (class attributes = attributs de classe), par affectation.

Ils sont en commun pour toutes les objet crée par la classe.

Souvent utilisés pour les « constantes » du type.

class Cercle:

PI = 3.14159

def __init__(self, r):

self.rayon = r

def aire(self):

return Cercle.PI * self.rayon ** 2

print('La valeur de PI est {}'.format(Cercle.PI))

c = Cercle(2.5)

print('rayon = {}, aire = {}'.format(c.rayon, c.aire()))

Classes

Un objet peut être composé par des autres objets.

Exemple : un rectangle est défini par deux points.

a = Vecteur(1, 2)

b = Vecteur(5, 4)

class Rectangle:

def __init__(self, p1, p2):

self.p1 = p1

self.p2 = p2

def aire(self):

largeur = self.p2.x – self.p1.x

hauteur = self.p2.y – self.p1.y

return largeur * hauteur

rect = Rectangle(a, b)

print(rect.aire())

Vecteur

x = 1y = 2

Vecteur

x = 5y = 4

Rectangle

aire()

p2 =

p1 =

Classes

Il n'y a pas d'attributs privés en Python, tout est toujours accessible.

Une convention est de préfixer avec un seule tiret bas les attributs qu'on veut protéger. Mais c'est juste une « suggestion » aux programmateurs.

class Chat:

def __init__(self):

self._age = 0

def set_age(self, age):

self._age = max(age, 0)

def get_age(self):

return self._age

Ce code suggère au programmateur qui veut utiliser la classe Chat, de ne pas toucher à _age et utiliser seulement set_age() et get_age().

Méthodes spéciales

On a rencontré pour la première fois une méthode spéciale __init__ (le constructeur).

Les méthodes spéciales sont identifiées par deux tirets bas à chaque côtés du nom.

class Chat:

def __init__(self, n, a):

self.nom = n

self.age = a

def parle(self, x):

print('miaou ' * x)

La fonctions repr()

La fonction repr() donne une représentation textuelle de n’importe quel objet, sous forme de chaîne.

>>> repr(4)

'4'

>>> def fun(x):

... return x + 2

>>> repr(fun)

'<function fun at 0x7f73ecad1ea0>'

>>> fichier = open('topics.txt')

>>> repr(fichier)

"<_io.TextIOWrapper name='topics.txt' mode='r' encoding='UTF-8'>"

Elle est utilisée dans l’interpréteur pour afficher les objets.

Méthodes spéciales

Pour les instances de classes, la conversion standard donne une chaîne du genre '<nomdumodule.nomdelaclasse object at 0xffff>'.

>>> class Vecteur:

... def __init__(self, x, y):

... self.x = x

... self.y = y

...

>>> p = Vecteur(3, 5)

>>> repr(p)

'<__main__.Vecteur object at 0x7f6d305b9ab8>'

Méthodes spéciales

Pour contrôler cette conversion il faut définir une méthode spéciale __repr__.

>>> class Vecteur:

... def __init__(x, y):

... self.x = x

... self.y = y

... def __repr__(self):

... return 'Vecteur({}, {})'.format(self.x, self.y)

...

>>> v = Vecteur(3, 5)

>>> repr(v)

'Vecteur(3, 5)'

>>> v

Vecteur(3, 5)

Méthodes spéciales

Sous le capot : la fonction repr appelle la méthode spéciale __str__ de l’objet.

repr(x) x.__repr__()

Tout se passe comme repr() était définie avec :

def repr(x):

return x.__repr__()

Méthodes spéciales et opérateurs

Méthodes spéciales

On peut utiliser les opérateurs + - * / < > etc... avec des objets. Par exemple, pour l'operateur + il faut définir une méthode __add__()

class Vecteur:

...

def __add__(self, other):

x = self.x + other.x

y = self.y + other.y

return Vecteur(x, y)

...

>>> v1 = Vecteur(3, 5)

>>> v2 = Vecteur(2, -1)

>>> v1 + v2 # équivalent à v1.__add__(v2)

# v1 est ‘self’ et v2 est ‘other’

Vecteur(5, 4)

Méthodes spéciales

+ __add__

- __sub__

* __mul__

/ __truediv__

// __floordiv__

< __lt__ (less than)> __gt__ (greater than)<= __le__ (less or equal)>= __ge__ (greater or equal)== __eq__

...

Recommended