Le constructeur de la classe attend deux paramètres : le nom et la couleur de la carte; ces valeurs, passées en argument au constructeur, sont les indices dans le tuple couleurs et la liste noms.
c1 = Carte(9, 1) # 9 = indice de 'COEUR' / 1 = indice de 'Valet'
Attention, on ne passe pas self en argument ( c'est déjà fait implicitement. )
D'après le principe d'encapsulation des attributs, on ne peut accéder directement à ceux-ci depuis "l'extérieur" de l'objet; il faut pour cela appeler les méthodes get_nom()
,
get_couleur()
et get_valeur()
appelées "accesseurs" ( = getter ) et destinées à ces accès :
print(c1.get_nom(), c1.get_valeur(), c1.get_couleur())
c2 = Carte(12, 3)
print(c2.get_nom(), c2.get_valeur(), c2.get_couleur())
On ne peut non plus modifier directement les attributs depuis "l'extérieur" de l'objet; il faut pour cela appeler la méthode setNom()
appelée "mutateur" ( = setter ) destinée
à cette modification :
c2.set_nom(11)
print(c2.get_nom(), c2.get_valeur(), c2.get_couleur())
c3 = Carte(6, 2)
Il faut appeler la méthode egalite()
( par exemple ) à partir d'un objet, et lui passer l'autre objet comme argument.
print(c3.egalite(c2))
print(c1.egalite(c3))
class Carte:
def __init__(self, nom, couleur):
# Affectation de l'attribut nom et de l'attribut couleur
couleurs = ('CARREAU', 'COEUR', 'TREFLE', 'PIQUE')
noms = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Valet', 'Dame', 'Roi', 'As']
valeurs = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Valet': 11, 'Dame': 12, 'Roi': 13, 'As': 14}
self.couleur = couleurs[couleur]
self.nom = noms[nom]
self.valeur = valeurs[self.nom]
def set_nom(self, nom):
# Mutateur de l'attribut nom (de la liste noms)
self.nom = nom
def get_nom(self):
# renvoie le nom de la carte (de la liste noms): Accesseur
return self.nom
def get_couleur(self):
# renvoie la couleur de la carte (de la liste couleur): Accesseur
return self.couleur
def get_valeur(self):
# renvoie la valeur de la carte (du dictionnaire valeurs) : Accesseur
return self.valeur
def egalite(self, carte):
''' Renvoie True si les cartes self et carte ont même valeur, False sinon
carte: Objet de type Carte
'''
if self.valeur == carte.get_valeur:
return True
else :
return False
def est_superieure(self, carte):
''' Renvoie True si la valeur de self est supérieure à celle de carte, False sinon
carte: Objet de type Carte
'''
if self.valeur > carte.get_valeur():
return True
else :
return False
def est_inferieure(self, carte):
''' Renvoie True si la valeur de self est inférieure à celle de carte, False sinon
carte: Objet de type Carte
'''
return self.valeur < carte.get_valeur():
Commentaires :
if...else...
(ligne 51 )La consigne était que la classe n'ait qu'un seul attribut : en effet, un cercle est entièrement défini par son rayon, lui rajouter une surface et un périmètre comme attributs supplémentaires est superflu et donc inutile.
Par contre, rien n’empêche d'utiliser des variables locales dans les méthodes pour le calcul de la surface et du périmètre avant de retourner ces valeurs, même si ce n'est pas indispensable ( on peut bien entendu retourner directement le résultat du calcul ).
from math import pi
class Cercle:
def __init__(self, rayon): # passage du rayon en argument au constructeur
self.rayon = rayon
def surface(self):
return pi*self.rayon**2
def perimetre(self):
return 2*pi*self.rayon
def est_plus_grand(self, c): # c est un argument de type 'Cercle'
return self.rayon > c.rayon # comparaison de l'attribut 'rayon' de self et de l'objet passé en argument et renvoi du résultat
On pouvait créer 5 instances complètement séparées de Cercle
, ou alors les regrouper dans une liste comme dans le TP "Champagne !" ; rien n'est imposé !
Par contre, il faut penser à passer la valeur du rayon en argument lors de l'instanciation : le constructeur attend ce paramètre.
c1 = Cercle(5)
c2 = Cercle(21.2)
c3 = Cercle(15)
c4 = Cercle(6)
c5 = Cercle(9.7)
surface()
et perimetre()
>>> c1.perimetre()
31.41592653589793
>>> c5.surface()
295.5924527762636
Il faut bien comprendre comment fonctionne la méthode est_plus_grand()
:
Cercle
, la consigne parle du deuxième : on écrira donc c2.est_plus_grand()
c2.est_plus_grand(c4)
>>> c2.est_plus_grand(c4)
True
c1 = Cercle(18)
print(c1)
>>> <__main__.Cercle object at 0x7f7196be6e50>
Il se passe d'ailleurs la même chose si on utilise print
avec le nom d'une fonction ( ou d'une méthode ) en oubliant les parenthèses : au lieu d'appeler la fonction et d'afficher le résultat
qu'elle renvoie, on affiche en fait l'adresse en mémoire de la fonction.
__str__
:
class Cercle:
...
def __str__(self):
return 'Rayon = ' + str(self.rayon)
...
from random import shuffle
class Chien :
def __init__(self, nom, aboiement, points_sante = 100):
self.nom = nom
self.points_sante = points_sante
self.aboiement = 'Grrr...' + aboiement
def mordre(self, autre_chien):
autre_chien.points_sante -= 10
def manger(self):
self.points_sante += 20
def grogner(self):
return self.aboiement
def machouiller(self, chaine):
chaine = list(chaine)
shuffle(chaine)
chaine = "".join(chaine)
return chaine
mordre()
(ligne 11 ) : elle prend en paramètre un objet de type Chien
, qui correspond ici à la variable autre_chien.shuffle()
du module random
, importé au début du script.Tout cela semble fonctionner...mais respecte-t-on bien tous les concepts de la POO ? En fait, non : on modifie directement l'attribut d'un autre objet dans la méthode mordre()
( ligne 12 ), ce qui ne respecte pas le principe
d'encapsulation des attributs : seul autre_chien devrait pouvoir modifier son attribut points_sante.
Il faudrait donc prévoir dans la classe une méthode destinée à modifier indirectement cet attribut à partir d'un autre objet; une telle méthode est appelée un mutateur ( ou setter en anglais ) :
def modifie_points_sante(self):
self.points_sante -= 10
La méthode mordre()
appellerait alors cette méthode, à partir de l'objet autre_chien :
def mordre(self, autre_chien):
autre_chien.modifie_points_sante()
Instancier quelques chiens ayant des noms et des aboiements différents :
>>> medor = Chien('Medor', 'ouaf') # valeur de points_sante par défaut ( 100 )
>>> kiki = Chien('Kiki', 'wah-wah', 50) # valeur de points_sante = 50
Faire manger un des chiens et vérifier que ses points de santé ont bien augmenté :
>>> medor.manger()
>>> medor.points_sante
120
Faire grogner un chien :
>>> medor.grogner()
'Grrr...ouaf'
Faire mâchouiller à un chien une chaîne de caractères quelconque :
>>> kiki.machouiller('Au pied!')
'!uepdAi '
Faire mordre un chien par un autre et vérifier que ses points de santé ont bien baissé :
>>> medor.mordre(kiki)
>>> kiki.points_sante
40
from time import sleep
class Horloge:
def __init__(self, heure, minutes, secondes):
self.heure = heure
self.minutes = minutes
self.secondes = secondes
def affiche(self):
print(self.heure, ':', self.minutes, ':', self.secondes)
def tic_tac(self):
self.secondes += 1
if self.secondes == 60:
self.secondes = 0
self.minutes += 1
if self.minutes == 60:
self.minutes = 0
self.heure += 1
if self.heure == 24:
self.heure = 0
horloge = Horloge(13,59,55)
while True:
horloge.affiche()
sleep(1)
horloge.tic_tac()
from random import randint
class Boite:
def __init__(self, longueur, largeur, hauteur):
self.longueur = longueur
self.largeur = largeur
self.hauteur = hauteur
def volume(self):
return self.longueur * self.largeur * self.hauteur
def rentre_dans(self, autre_boite):
return autre_boite.longueur > self.longueur and autre_boite.largeur > self.largeur and autre_boite.hauteur > self.hauteur # on teste si les TROIS dimensions de la deuxième boîte sont plus petites
def tri_selection(boites):
for i in range(len(boites)):
mini = i
for j in range(i+1, len(boites)):
if boites[j].volume() > boites[mini].volume():
mini = j
if mini != i:
boites[i], boites[mini] = boites[mini], boites[i]
# Création du tableau de 20 objets Boite
boites = []
for i in range(20):
boites.append(Boite(randint(1, 50), randint(1, 50), randint(1, 50)))
# tri de la liste des boîtes
tri_selection(boites)
# Construction de la suite des boîtes gigognes
suite = [boites[0]]
for i in range(1, len(boites)):
if boites[i].rentre_dans(suite[-1]): # si la boite du plus grand volume possible rentre dans la dernière boîte de la suite
suite.append(boites[i])
# Vérification
for boite in suite:
print("L =", boite.longueur, "l =", boite.largeur, "h =", boite.hauteur)