Je regarde cela dès que j'ai du temps libre... Merci pour la participation.
Ce qu'il y a de bien c'est que tu te autocritiques, et cela assez justement. L'essentiel est déjà de trouver cela formateur et d'avoir progressé dans un domaine qui semble être dans la syntaxe python.
Dans la POO, même si tu ne t'en rends pas compte, tu as sans doute dû réfléchir à une implantation, et cela, c'est débuté dans la POO, doucement mais sûrement
Le cas de Stakhanov m'intéresse car il gère les erreurs à l'intérieur de ses classes. C'est justement une question que je me posais: Faut-il gérer les erreurs dans la classe (comme il a fait), ou les gérer dans le main (comme j'ai fait)?
Oui t'inquiète je l'avais bien lu dans ton premier message que tu n'avais pas géré de manière optimale les erreurs. Non ce qui m'intéresse vraiment, c'est de savoir si la gestion doit être interne à la classe ou externe (dans le main).
Il n'y a pas de réelles positions concernant les exceptions, tout se fait.
Dans la situation actuelle avec la POO, je créerais ma propre classe héritant de la classe Exception. C'est une forme d'implémentation dont on peut se soucier tout à la fin, quand le problème est résolu, et qu'on doit réfléchir aux contraintes discutables des erreurs utilisateur.
"je ne comprend pas comment marche le système de credit ?"
C'est simple, il faut que tu considère que la pharmacie ne rend jamais la monnaie. Donc si le client doit payer 18,55€ et qu'il donne un billet de 20€, la pharmacie lui doit 1,45€. Soit un crédit négatif pour la pharmacie.
credit = -1.45
Par contre si le client ne donne que 18€, il devra 0,55€ à la pharmacie.
credit = 0.55
Maintenant pour mettre à jour le crédit du client, il faut tenir compte du total à payer, de ce que paie réellement le client et de ce qu'il doit déjà à la pharmacie:
credit = total - payer + credit
#ou:
credit += total - payer
Donc si le client a un total de 18,55€ de médicaments, qu'il paie 20€, mais qu'il doit déjà 5€ à la pharmacie:
credit = 3.55 #18,55€ - 20€ + 5€ -> le client doit encore 3,55€ à la pharmacie
Moi aussi j'ai ça. C'est un peu casse-couille, mais pour un affichage propre, tu peux utiliser la méthode format(:2f) pour par exemple avoir un flottant avec 2 chiffres après la virgule:
credit = 18.55 - 20 + 5
print("Le crédit est de {:2f}€".format(credit))
#Ou sinon d'utiliser la fonction built-in round() en indiquant en deuxième argument la précision souhaitée:
credit = round(credit, 2)
J'en profite pendant que je fais du python pour soumettre ce que j'ai fait, avec quelques modifications =)
#!/usr/bin/env python3
import sys
"""
"" Client class
""
"" Un client est un nom avec une ardoise
"""
class Client:
def __init__(self, nom):
self.nom = nom
self.credit = 0.0
def setCredit(self, value):
self.credit += value
def getCredit(self):
return (self.credit)
def getNom(self):
return (self.nom)
"""
"" Medicament class
""
"" Un medicament est un nom avec un prix et une quantite disponible
"""
class Medicament:
def __init__(self, nom, prix, stock):
self.nom = nom
self.prix = prix
self.stock = stock
def setPrix(self, prix):
self.prix = prix
def setStock(self, stock):
self.stock += stock
def getNom(self):
return (self.nom)
def getPrix(self):
return (self.prix)
def getStock(self):
return (self.stock)
"""
"" Pharmacie class
"""
class Pharmacie:
def __init__(self):
self.menu = [
('Achat de medicament', self.achat),
('Approvisionnement en medicaments', self.approvisionnement),
('Etats des stocks et des credits', self.affichage),
('Quitter', self.quitter)
]
self.shall_i_continue = True
"""
Possible lecture a partir d'un fichier
"""
self.clients = [ Client('Malfichu'), Client('Palichon') ]
self.medicaments = [ Medicament('Aspiron', 5, 10), Medicament('Rhinoplexil', 3, 10) ]
"""
Gestion generique de lecture de liste, avec 'phrase' a afficher par la fonction input()
Si l'entree saisie n'est pas dans la liste, afficher la liste
TODO : si l'entree saisie n'est pas dans la liste, proposer sa creation
"""
def lireListeDe(self, objet, phrase):
while True:
entry = input(phrase)
for item in objet:
if item.getNom() == entry:
return (item)
print('Entree trouvee : ')
for item in objet:
print(item.getNom())
print('{} n\'existe pas dans la liste'.format(entry))
"""
Gestion generique de la lecture d'un entier
"""
def lireEntier(self, phrase):
while True:
entry = input(phrase)
if entry.isdigit() and int(entry):
return (int(entry))
"""
Une fois que tout ce qu'a saisi l'utilisateur est valide, on verifie que le medicament
est present en quantite suffisante.
Si oui, on decremente le stock et on set son ardoise
"""
def achat(self):
client = self.lireListeDe(self.clients, 'Nom du client :\n')
medicament = self.lireListeDe(self.medicaments, 'Nom du medicament :\n')
paiement = self.lireEntier('Montant du paiement :\n')
quantite = self.lireEntier('Quantite :\n')
if medicament.getStock() < quantite:
print('Il ne reste que {}pc de {}'.format(medicament.getStock(), medicament.getNom()))
else:
medicament.setStock(-quantite)
print('{}pc de {} a {}€ = {}€'.format(quantite,
medicament.getNom(),
medicament.getPrix(),
quantite * medicament.getPrix()))
client.setCredit((quantite * medicament.getPrix()) - paiement)
"""
Je crois que ca va aller niveau comprehension :>
"""
def approvisionnement(self):
medicament = self.lireListeDe(self.medicaments, 'Nom du medicament :\n')
quantite = self.lireEntier('Quantite :\n')
medicament.setStock(quantite)
"""
Simple parcours de liste pour afficher
"""
def affichage(self):
print('Affichage des stocks')
for medicament in self.medicaments:
print('Stock du medicament {} : {}'.format(medicament.getNom(), medicament.getStock()))
print('Affichage des credits')
for client in self.clients:
print('Credit du client {} : {}'.format(client.getNom(), client.getCredit()))
"""
Interruption de la boucle
"""
def quitter(self):
print('Programme terminé!')
self.shall_i_continue = False
"""
Le menu est une liste de tuple avec un label et une fonction.
Ici, on affiche uniquement le label, qui se trouve a l'index 0 du tuple
"""
def printMenu(self):
print('\n')
for index, label in enumerate(self.menu):
print('{} : {}'.format(index, label[0]))
"""
Boucle infinie qui affiche le menu et execute la fonction associee si l'index
selectionne existe
"""
def loop(self):
while self.shall_i_continue:
self.printMenu()
choice = input()
if choice.isdigit() and int(choice) in range(len(self.menu)):
self.menu[int(choice)][1]()
return (0)
if __name__=='__main__':
app = Pharmacie()
status = app.loop()
sys.exit(status)
Quelques commentaires :
Je gère le menu avec une liste de tuple, ce que je trouve plus pratique. En cas d'ajout d'éléments dans le menu, il suffit de peupler la liste et d'implémenter la fonction associée. Bon, l'index commence à 0, mais bon
lireMedicament() et lireClient() font la même chose : parcourir une liste et renvoyer un élément. La fonction lireListeDe() regroupe ça en une fonction, en passant la liste directement. Seul bémol, à la base, si l'utilisateur rentrais un medicament ou un client qui n'existais pas, je voulais lui demander s'il voulait l'insérer dans la liste. Avec cette méthode, je ne vois pas comment faire ça proprement, sans faire de condition sur le type d'objet de la liste,
# -------------------------------------------------------------------------------
# Class et Fonction
#-------------------------------------------------------------------------------
#Class -------------------------------------------------------------------------
#Class Client
class Client():
"""Client"""
def __init__(self, credits, nom_client):
self.credits = credits #Argent du client
self.nom_client = nom_client #Nom du client
class Medicament():
"""Class medicament"""
def __init__(self, nom_medicament, prix_medicament, stock_medicament):
self.nom_medicament = nom_medicament #Nom du medicament
self.prix_medicament = prix_medicament
self.stock_medicament = stock_medicament
#Class Pharmacie
class Pharmacie():
"""Class qui gère la Pharmacie"""
def __init__(self):
#Client
self.liste_des_client = [Client(0, "Jean-Pierre"), Client(5, "Regis"), Client(0, "Marc")]
#Medicament
self.liste_des_medicament = [Medicament("Aspirine", 12, 9), Medicament("Cachet", 2, 89),Medicament("Dentifrice",18.55,12)]
self.menu() #On lance le menu quand la class est initilisé
def menu(self):
"""Methode qui affiche le menu de la class Pharmacie"""
continuer = True
choix = 4
while continuer:
try:
choix = int(input(
"1 : Achat de medicament\n2 : Approvisionnement en medicaments\n3 : Etats des stocks et des credits\n4 : Quitter\n"))
except ValueError:
pass
else:
continuer = False
if choix == 1:
"""Achat d'un medicament"""
self.achat()
elif choix == 2:
""" Approvisionnement d'un medicament"""
self.approvisionnement()
elif choix == 3:
""" Etats des stocks et des credits"""
self.affichage()
elif choix == 4:
""" Quitter"""
pass
def affichage(self):
"""Affiche les medicament et les client"""
print("Affichage des stocks",)
print("".join(["Stock du medicament {} :{}\n".format(i.nom_medicament,i.stock_medicament) for i in self.liste_des_medicament]))
print("Affichage des credits")
print("".join(["Credit du client {} : {}\n".format(i.nom_client,i.credits) for i in self.liste_des_client]))
self.menu() #On retourne au menu
def quitter(self):
"""Fonction qui quitte le programme """
print("programme terminé!")
def approvisionnement(self):
"""Aprovisonne les medicament"""
medicament = self.lireMedicament()
while 1:
try:
quantite_medicament = int(input("Donner la Quantite : \n"))
except ValueError:
pass
else:
break
for i in self.liste_des_medicament:
if i.nom_medicament == medicament:
i.stock_medicament += quantite_medicament
self.menu() #On retourne au menu
def achat(self):
"""Fonction qui permet d'acheter les medicaments"""
client = self.lireClient()
medicament = self.lireMedicament()
somme_medicament = 0
client = [i for i in self.liste_des_client if i.nom_client == client][0]
medicament = [i for i in self.liste_des_medicament if i.nom_medicament == medicament][0]
while 1:
try :
montant_somme = float(input("quel est le montant du paiement?\n")) #Le client donne par example 20€
qantiter_acheter = float(input("quelle est la quantite achetee?\n")) #Le client veut un certaine quantité
if medicament.stock_medicament < qantiter_acheter:
print("Achat Impossible. Quantite insuffisante\n")
break
qantiter_somme = medicament.prix_medicament*qantiter_acheter
client.credits = qantiter_somme-montant_somme +client.credits
client.credits = round(client.credits,2)
except ValueError:
pass
else:
break
self.menu()
#-------------------------------------------------------------------------------------------------------------------
#Fonction auxiliare (lireClient....)
#-------------------------------------------------------------------------------------------------------------------
def lireClient(self):
"""Cette methode lis les client (Tant que le client n'est pas bon, elle redemande le nom d'un client"""
existe_client = True
while existe_client:
nom_client = input("Nom du client?: ")
if [i for i in self.liste_des_client if i.nom_client == nom_client] != []:
existe_client = False
return nom_client
else:
print("Client inconnu. Veuilliez recommencer")
def lireMedicament(self):
"""Cette methode lis les medicament (Tant que les medicament n'est pas bon, elle redemande le nom du medicament"""
existe_medicament = True
while existe_medicament:
nom_medicament = input("Nom du medicament?: ")
if [i for i in self.liste_des_medicament if i.nom_medicament == nom_medicament] != []:
existe_medicament = False
return nom_medicament
else:
print('Medicament inconnu. Veuilliez recommencer')
if __name__ == "__main__":
pharmacie = Pharmacie()
Comme l'exercice était fait pour le Java, je me suis dit pourquoi pas le faire en Java.
Voici le code :
Main :
package com.company;
public class Main {
public static void main(String[] args) {
Client[] tableauxClient = {new Client("Marc",50.0d), new Client("Regis",12.0d), new Client("Cirdo",5.0d)};
Medicament[] tableauxMedicament = {new Medicament(),new Medicament("Aspirine",20.0d,60), new Medicament("Cachet",12.0d,20),new Medicament("Dentifrice",18.55d,12) };
Pharmacie pharmacie = new Pharmacie(tableauxClient,tableauxMedicament);
}
}
Pharmacie :
package com.company;
import java.util.Scanner;
public class Pharmacie {
Client[] tabClient = {}; //On accèpte que 11 client
Medicament[] tabMedicament = {};
public Pharmacie(Client[] client,Medicament[] medicaments){
tabClient = client;
tabMedicament = medicaments;
this.menu();
}
public void menu(){
//Affiche
Scanner scanner = new Scanner (System.in);
System.out.println("1 : Achat de medicament\n2 : Approvisionnement en medicaments\n3 : Etats des stocks et des credits\n4 : Quitter");
int reponse = scanner.nextInt();
if (reponse == 1){ //Achat d'un médicament
this.achat();
}else if (reponse == 2){ //Approvionnement d'un medicament
this.approvisionnement();
}else if (reponse == 3){ // Etat des stocks
this.affichage();
}else if (reponse == 4){ //Quitter
this.quitter();
}
}
/*
Méthode Public
*/
public void achat(){
//Permet de faire l'achat
Scanner scannner = new Scanner(System.in);
int indexClient = this.lireClient();
int indexMedicament = this.lireMedicament();
double montantPaiement = 0.0d;
double quantiterPaiement = 0.0d;
double sommePaiement = 0.0d;
System.out.println("quel est le montant du paiement?");
montantPaiement = scannner.nextDouble();
scannner.nextLine();
System.out.println("quelle est la quantite achetee?");
quantiterPaiement = scannner.nextDouble();
sommePaiement = this.tabMedicament[indexMedicament].prixMedicament *quantiterPaiement;
System.out.println(sommePaiement);
this.tabClient[indexClient].creditClient = this.arrondi(sommePaiement-montantPaiement+this.tabClient[indexClient].creditClient,2);
System.out.println(this.tabClient[indexClient].creditClient);
this.menu();
}
public void approvisionnement(){
//Fonction qui appovisionne les medicament
int index = this.lireMedicament();
Scanner scanner = new Scanner(System.in);
System.out.print("Donner la Quantite : ");
int i = scanner.nextInt();
this.tabMedicament[index].stockMedicament += i;
this.menu();
}
public void affichage(){
//Fonction qui affiche les credits des personnes et qui affiche le stock des medicaments
System.out.println("Affichage des stocks");
for (Medicament v: this.tabMedicament)
System.out.println("Stock du medicament "+v.nomMedicament+" :"+v.stockMedicament);
System.out.println("Stock du medicament");
for (Client c : this.tabClient)
System.out.println("Credit du client "+c.nomClient+" :"+c.creditClient);
System.out.println("\n");
this.menu();
}
public void quitter(){
System.out.println("programme terminé!");
}
/*
Méthode auxiliare (Private)
*/
private double arrondi(double A, int B) {
return (double) ( (int) (A * Math.pow(10, B) + .5)) / Math.pow(10, B);
}
private int lireClient(){
Scanner scanner = new Scanner(System.in);
//On cherche dans le tableaux le nom
int i = 0; //Incrémenteur
int indexReponse =-1;
while (indexReponse == -1) {
System.out.print("Nom du client?: ");
String reponse = scanner.nextLine();
for (Client c : this.tabClient) {
if (c.nomClient.equals(reponse))
indexReponse = i;
i++;
}
//Message d'erreur
if (indexReponse == -1){
System.out.println("Client inconnu. Veuilliez recommencer");
i = 0;
}
}
return indexReponse;
}
private int lireMedicament(){
Scanner scanner = new Scanner(System.in);
//On cherche dans le tableaux le nom
int i = 0; //Incrémenteur
int indexReponse =-1;
while (indexReponse == -1) {
System.out.print("Nom du medicament?: ");
String reponse = scanner.nextLine();
for (Medicament m : this.tabMedicament) {
if (m.nomMedicament.equals(reponse))
indexReponse = i;
i++;
}
//Message d'erreur
if (indexReponse == -1){
System.out.println("Medicament inconnu. Veuilliez recommencer");
i =0;
}
}
return indexReponse;
}
}
Client :
package com.company;
public class Client{
//Variable
String nomClient;
double creditClient;
//Constructeur par défault
public Client(){
nomClient = "Aucun";
creditClient = 0.0d;
}
//Constructeur avec des paramètres
public Client(String pNomClient,double pCreditClient){
nomClient = pNomClient;
creditClient = pCreditClient;
}
}
Pharmacie :
package com.company;
public class Medicament {
String nomMedicament;
double prixMedicament;
int stockMedicament;
//Constructeur par défault
public Medicament(){
nomMedicament = "Aucun";
prixMedicament = 0.0d;
stockMedicament = 0;
}
//Constructeur avec paramètre
public Medicament(String pNomMedicament,double pPrixMedicament,int pStockMedicament){
nomMedicament = pNomMedicament;
prixMedicament = pPrixMedicament;
stockMedicament = pStockMedicament;
}
}
Merci à Olygrim pour m'avoir aidé sur le fonctionnement du crédit.
J'espère qu'il n'est pas trop tard pour poster sur cet exercice ...
Je l'ai trouvé très instructif pour réfléchir sur la POO, en particulier en considérant qu'on doit pouvoir gérer plusieurs pharmacies. J'ai pas mal cogité (et modifié le code) sur les spécifications globales : par ex., où et comment gérer les médocs et les stocks si plusieurs pharmacies.
Les choix sont expliqués en début du programme (on aurait pu en faire d'autres). Voici le code :
### exercice pharmacie :
#
# choix d'implantation :
#
# - on doit pouvoir gérer plusieurs pharmacies (création de classe Pharmacie))
# - les mêmes médicaments peuvent être fournis par plusieurs pharm.
# (nom et prix communs dans dictionnaire 'leVidal')
# mais le stock est propre à chacune
# - les clients sont gérés localement : client et son crédit attachés à la pharm.
# - en dissociant le credit de l'instance Client, on facilite la création éventuelle
# d'une base de clientèle commune à plusieurs pharm.
# - nomenclature, clientèle et stock gérés en dictionnaires
# pour recherche par nom accélérée
# - pour éviter les homonymies (dictionnaire oblige),
# on introduit le numéro sécu sociale comme clé client (et pas le nom)
# - la nomenclature des medocs (leVidal) est implementée en variable globale
# pour accéder à l'info de medoc 'prix' à partir d'une pharmacie :
# on pourrait éviter ça en organisant les stocks par pharm. en tuples
# (instance medoc , quantité)
# au lieu de les gérer seulement en quantité en stock
#
class Pharmacie():
""" crée un magasin "pharmacie" """
def __init__(self):
self.clientele = {} # associera num sécu client (clé) à 2-tuple :
# (instance client, crédit)
self.stock = {} # associera nom medoc (clé) à quantité dispo
def lire_client(self):
""" demande et retourne un numero ss de client de cette pharm. """
while True :
noss = input(" Client (numéro sécu) ? ")
try :
noss = int(noss)
except :
print("On attend un numéro !")
continue
if noss in self.clientele :
return noss
else :
print("Client inconnu !")
def achat(self, noss_cli, nom_med, quant, reglement):
""" transaction dans cette pharmacie :
le 'client' veut des 'medoc's en 'quant'ité et verse 'reglement' euros :
- retourne le tuple (quantité fournie , coût)
- signale si rupture de stock
"""
global leVidal # nécessaire pour connaitre prix medocs
prix = leVidal[nom_med].prix
enstock = self.stock.get(nom_med,0) # 0 si medoc pas en stock
if quant <= enstock :
qfournie = quant
enstock -= quant
else :
qfournie = enstock
enstock = 0
print ("*** Approvisionner ", nom_med, " ***")
if enstock :
self.stock[nom_med] = enstock # maj stock
else :
self.stock.pop(nom_med) # on vire du stock les références vides
cout = prix * qfournie
# si reglement > coût, le delta vient en débit client (crédit négatif)
cli, credit = self.clientele[noss_cli] # maj credit client
credit += cout - reglement
self.clientele[noss_cli] = (cli, credit)
return (qfournie, cout)
def appro(self, nom_medoc, quant):
""" approvisionne cette pharm. en 'quant'ité de medoc 'nom_medoc' """
enstock = self.stock.get(nom_medoc, 0) # 0 si medoc pas en stock
# mettre à jour quantité en stock
# nb : crée le medoc dans le stock s'il n'y était pas
self.stock[nom_medoc] = enstock + quant
def dump(self):
""" liste la clientèle et l'état des stocks de la pharm. """
global leVidal
print("*** clientèle : ***")
for cli, credit in self.clientele.values() :
print(" crédit du client {0:<12} = {1:8.2f}".format(cli.nom, credit))
print("*** état du stock ***")
for nom, quant in self.stock.items() :
prix = leVidal[nom].prix
print(" stock du médicament {0:<12} = {1:4d} (prix unit. {2:8.2f}) "
.format(nom, quant, prix))
print()
class Client():
""" génère un client : numero sécu, nom
- le crédit est géré au niveau de la pharm.
- clé d'accés : numero sécu (unique)
pourrait recevoir des infos en plus (adresse, teleph. ...)
"""
def __init__(self, noss, nom):
self.noss = noss
self.nom = nom
class Medoc():
""" génère un article médicament : nom , prix de vente
- la quantité en stock est gérée au niveau de la pharmacie
- cle d'accés : le nom
pourrait recevoir des infos en + (fournisseur, remboursement ...)
"""
def __init__(self, nom, prix):
self.nom = nom
self.prix = prix
# fonctions globales indépendantes de la pharmacie :
def lire_medoc() :
""" demande et retourne un nom de medoc nomenclaturé """
while True :
nom_med = input(" Médicament ? ")
if nom_med in leVidal :
return nom_med
else :
print("Médicament inconnu !")
def lire_choix_menu():
""" retourne le choix 1 à 4 dans le menu """
print("""1 : Achat de medicament
2 : Approvisionnement en medicaments
3 : Etats des stocks et des crédits
4 : Quitter""")
while True :
rep = input("choix ? ")
try :
choix = int(rep)
except ValueError :
pass
else :
if choix in range(1,5):
return choix
def lire_quant():
""" demande une quantité (retourne entier positif) """
while True :
rep = input(" Quantité ? ")
try :
qt = int(rep)
except ValueError :
continue
if qt > 0 :
return qt
print("La quantité doit être un nombre positif !")
def lire_reglement():
""" demande et retourne le montant versé en réglement """
while True :
rep = input(" Montant réglé ? ")
try :
qt = float(rep)
except ValueError :
continue
if qt >= 0 :
return qt
print("Le montant doit être positif ou nul !")
########## créer le dictionnaire des medocs : leVidal
# clé : nom du medoc , valeur = instance de Medoc
leVidal = {}
for nom, prix in (("Aspro",2.5), ("Doliprane",3.4), ("Upsa",15),
("Vioxx",35), ("AntiSIDA",2999.99)):
leVidal[nom] = Medoc(nom, prix) # instancier les medocs
########## création et init de la pharmacie ############
ph = Pharmacie()
for noss, nom in ((1,"Tordu"), (3,"Estropié"), (5,"Mal Fichu")):
ph.clientele[noss] = (Client(noss, nom), 0.0) # création clients et init clientele
for nom in ("Aspro","Doliprane","Upsa"): # init stocks sur certains medocs
prix = leVidal[nom].prix
qt = int(200 // prix ) # stock init à 200 euros maxi / medoc
ph.stock[nom] = qt
######### boucle de lecture ##############
# toutes les actions sont sur la pharmacie ph #
while True :
choix = lire_choix_menu()
if choix == 1 : # achat
# demander noss client, medoc, quant, montant réglé :
nb, cout = ph.achat(ph.lire_client(), lire_medoc(),
lire_quant(), lire_reglement())
print(" (=> quantité vendue : {0} pour : {1:8.2f} Euros)"
.format(nb, cout))
elif choix == 2 : # appro
# demander nom medoc et quantité :
ph.appro(lire_medoc(), lire_quant())
elif choix == 3 : # état clientèle et stocks
ph.dump()
else :
break
print ("Au revoir")
Ca marche ... mais j'aimerai avoir des avis sur les choix d'implantation par ex. et sur le codage ...Merci
def __init__(self):
"""attributs de la classe Pharmacie() qui gère les clients et les
médicaments; les 4 dernières variables sont utilisés dans les
méthodes achat(), approvisionnement() et affichage()"""
self.client = Client()
self.medicament = Medicament()
self.clt = None
self.med = None
self.qte = None
self.money = None
def achat(self):
"""traiter un achat fait par un client. l'achat porte sur un
médicament donné dans une quantité donnée. Pour cette transaction le
client paie un certain prix. Une opération d'achat aura pour effet de
déduire la quantité achetée du stock du médicaments correspondant et
d'augmenter le crédit du client (d'un montant équivalent au montant
de l'achat moins la somme payée). Les noms du client et du médicament
sont lus depuis le terminal. Le programme boucle jusqu'à
introduction de noms connus aussi bien pour les clients que
les médicaments. Ces procédures de vérification sont prises en
charge par les méthodes lire_client() et lire_medicament()"""
self.clt = self.client.lire_client()
self.med = self.medicament.lire_medicament()
self.qte = self.medicament.stock_medicament()
while True:
try:
self.money = int(input("Combien payez-vous? "))
break
except ValueError:
print("Veuillez entrer un nombre!")
for k, v in self.medicament.identite_stock.items():
if self.med == k:
self.medicament.identite_stock[self.med] = v - self.qte
for k, v in self.client.compte.items():
if self.clt == k:
self.client.compte[self.clt] = v - self.money
def approvisionnement(self):
"""approvisionner le stock d'un médicament. Le nom du médicament à
approvisionner ainsi que la quantité à ajouter au stock sont lus
depuis le terminal. Lorsque le nom du médicament est introduit,
on vérifie s'il s'agit bien d'un nom connu dans la liste des
médicaments de la pharmacie. Le programme boucle jusqu'à
introduction d'un nom correct. Cette procédure de vérification est
prise en charge par la méthode lire_medicament()"""
self.med = self.medicament.lire_medicament()
self.qte = self.medicament.stock_medicament()
for k, v in self.medicament.identite_stock.items():
if self.med == k:
self.medicament.identite_stock[self.med] = v + self.qte
def affichage(self):
"""afficher les clients et leurs crédits respectifs ainsi
que les médicaments et leurs stocks respectifs"""
self.client.afficher_compte()
self.medicament.afficher_stock()
def quitter(self):
"""fin du programme"""
print("Programme terminé!")
class Client(object):
def __init__(self):
"""dictionnaire qui regroupe les clients et leurs credits respectifs"""
self.compte = {"bapetel": 200, "nasser": 300}
"""variables qui seront utilisés dans les méthodes de notre classe"""
self.nom = None
self.quantite = None
self.identite = None
def lire_client(self):
"""lire le nom du client depuis le terminal; la boucle se ferme
si et seulement si le nom du client est connu"""
while True:
self.nom = input("Entrez votre nom: ")
for k, v in self.compte.items():
if self.nom == k:
return self.nom
def afficher_compte(self):
"""afficher les clients et leurs credits respectifs"""
print("Clients et leurs crédits respectifs")
for k,v in self.compte.items():
print("{:<15}{:>15}".format(k, v))
class Medicament(object):
def __init__(self):
"""dictionnaire qui regroupe les médicaments et leurs stocks"""
self.identite_stock = {"aspirine": 50, "paracetamol": 60}
def stock_medicament(self):
"""lire le stock de médicament depuis le terminal; la boucle se ferme
si et seulement si le stock est un nombre entier"""
while True:
try:
self.quantite = int(input("Entrez la quantité : "))
break
except ValueError:
print("Veuillez entrez un nombre entier!")
return self.quantite
def lire_medicament(self):
"""lire le nom du médicament depuis le terminal; la boucle se ferme
si et seulement si le nom du médicament est connu"""
while True:
self.identite = input("Entrez le nom du médicament: ")
for k, v in self.identite_stock.items():
if self.identite == k:
return self.identite
def afficher_stock(self):
"""afficher les clients et leurs credits respectifs """
print("\nMédicaments et leurs stocks respectifs")
for k, v in self.identite_stock.items():
print("{:<15}{:>15}".format(k, v))
PROGRAMME PRINCIPAL
p = Pharmacie()
lire le choix depuis le terminal; la boucle se ferme
si et seulement si le choix est un nombre entier
compris entre 1 et 4
while True:
try:
choix = int(input("""\nQue voulez-vous faire?
1- Achat de médicament
2- Approvisionnement en médicament
3- Afficher l'état des stocks et des crédits
4- Quitter
"""))
if choix in range(1,5):
if choix == 1:
p.achat()
elif choix == 2:
p.approvisionnement()
elif choix == 3:
p.affichage()
elif choix == 4:
p.quitter()
break
except ValueError:
print("Veuillez choisir un nombre entre 1 et 4")
@Bapetel : ton code tel qu'il apparaît dans ton post est difficile à lire ! Utilise l'outil </> de la barre au-dessus de la fenêtre de saisie : il ouvre une fenêtre où tu n'as plus qu'à copier ton code pour l'insérer de façon très propre dans le post. Pratique et efficace !
Bonjour! Cela fais à peine 3 semaines que je me suis mis à Python après les conseils d'un ami et je suis assez content d'avoir trouvé ce petit exercice pour s'entrainer à de la POO.
Du coup je vous soumets mon code et j'ai aussi quelques questions. D'abord, pour les classes Client et Médicament j'ai défini des accesseurs et des mutateurs. Mais j'ai l'impression que dans ce cadre, ils sont assez superflus.. à votre avis sont-ils vraiment utiles et si non, quand les utiliser? Et de plus, est-il conseillé que tout le programme ne soit en fait que des fonctions qui renvoient d'autres fonctions... C'est à dire que en dehors des classes et des fonctions, je n'ai qu'une boucle, de trois lignes. J'ai toujours l'impression d'abuser des fonctions et j'aimerais avoir votre avis là dessus.
Mais bon trêve de questionnement, je suis là pour montrer mon code:
Premièrement la classe Pharmacie, avec laquelle je crée seulement un seul objet et qui contient 90% de toutes les fonctions de mon programme (lire médicament et client, afficher, acheter, approvisionner...)
class Pharmacie:
"""La classe Pharmacie qui cointient toutes les fonctions permettant l'affichage, l'approvisionnement et l'achat (avec des fonctions réutilisables qui lisent le nom du client, du médicament ou la quantité voulue"""
#Initialisé juste à l'aide de la liste des médicaments et des clients
def __init__(self, liste_medicament, liste_client):
self.liste_medicament = liste_medicament
self.liste_client = liste_client
#permet l'affichage des stocks et des crédits grâce aux listes
def affichage(self):
print("Affichage des stocks:")
for stock_medoc in self.liste_medicament:
print(stock_medoc)
print("Affichage des crédits:")
for clients in self.liste_client:
print(clients)
#Récupère l'objet client à l'aide de son nom
def lire_client(self):
print("Entrez le nom du client:")
retour_client = False
while True:
nom_client = input("-")
for client in self.liste_client:
if nom_client.lower() == client.nom.lower():
retour_client = client
if retour_client:
break
else:
print("Le client spécifié n'est pas présent dans la liste")
return retour_client
#Récupère l'objet médicament à l'aide de son nom
def lire_medicament(self):
print("Entrez le nom du médicament:")
retour_medoc = False
while True:
nom_medoc = input("-")
for medicament in self.liste_medicament:
if nom_medoc.lower() == medicament.nom.lower():
retour_medoc = medicament
if retour_medoc:
break
else:
print("Le médicament choisi n'est pas présent dans la liste:")
return retour_medoc
#Récupère une quantité (réutilisée 2 fois)
def lire_qt(self):
print("Entrez la quantité:")
while True:
qt = input("-")
try:
qt = int(qt)
except ValueError:
print("Entrez une quantité valable")
continue
else:
if qt >= 1:
return qt
#Approvisionne la pharmacie
def approvisionnement(self):
print("Approvisionnement:")
medicament_a_approv = self.lire_medicament()
qt = self.lire_qt()
medicament_a_approv.quantite += qt
#Permet l'achat de médicaments par un client
def achat(self):
client = self.lire_client()
medicament = self.lire_medicament()
while True:
qt = self.lire_qt()
if qt > medicament.quantite:
print("Il n'y a pas assez de médicaments disponibles.")
qt = self.lire_qt()
else:
break
print("Entrez le montant du paiement:")
while True:
paiement = input("-")
try:
paiement = float(paiement)
except ValueError:
print("Entrez un montant de paiement valable")
continue
else:
if paiement >= 1:
break
client.credit += (medicament.prix * qt) - paiement
medicament.quantite -= qt
print("{} a acheté {} {} et a payé {}.".format(client.nom, medicament.nom, qt))
Deuxièmement, les classes médicament et Client qui ne contiennent que les accesseurs et mutateurs:
class Medicament:
"""la classe médicament qui met à jour la liste des médicaments et contient les accésseurs et mutateurs sécurisés."""
liste_medicament = list()
#Une fois initialisé avec ces paramètres, l'objet se rajoute dans la liste des médicaments
def __init__(self, nom, prix, qt=10):
self._nom = nom
self._prix = prix
self.quantite = qt
Medicament.liste_medicament.append(self)
def _get_nom(self):
return self._nom
def _set_nom(self, nom):
print('Vous ne pouvez pas modifier le nom de ce médicament')
nom = property(_get_nom, _set_nom)
def _get_prix(self):
return self._prix
def _set_prix(self, prix):
print('Vous ne pouvez pas modifier le prix de ce médicament')
prix = property(_get_prix, _set_prix)
def __str__(self):
return "Stock du médicament {}: {} pour un prix de {}€".format(self.nom, self.quantite, self.prix)
def __repr__(self):
return "Nom: {} - Prix: {}€ - Quantité: {}".format(self.nom, self.prix, self.quantite)
class Client:
"""la classe client qui met à jour la liste des clients et contient les accésseurs et mutateurs sécurisés."""
liste_client = list()
#Une fois initialisé avec ces paramètres, l'objet se rajoute dans la liste des clients
def __init__(self, nom, credit=0.0):
self._nom = nom
self.credit = float(credit)
Client.liste_client.append(self)
def _get_nom(self):
return self._nom
def _set_nom(self):
print('Vous ne pouvez pas changer le nom d\'un client')
nom = property(_get_nom, _set_nom)
def __str__(self):
return "{} a un crédit de {}.".format(self.nom.capitalize(), self.credit)
def __repr__(self):
return "Mr/Mme {} a un crédit de {}.".format(self.nom, self.credit)
Puis la création de tous mes objets:
#Initialisation de la pharmacie
pharmacie = Pharmacie(Medicament.liste_medicament, Client.liste_client)
#Ajout des médicaments
Aspirine = Medicament("Aspirine", 5, 10)
Doliprane = Medicament("Doliprane", 7, 15)
Smecta = Medicament("Smecta", 9, 22)
Donormil = Medicament("Donormil", 9, 13)
#Ajout des clients
Paul = Client("Paul")
Christian = Client("Christian")
Etienne = Client("Etienne", 5)
Avant de terminer par le cœur du programme qui ne tient qu'en une poignée de lignes:
#Gère le menu du prorgamme et les choix
def main():
while True:
print("\n")
print("1 : Achat de medicament")
print("2 : Approvisionnement en medicaments")
print("3 : Etats des stocks et des credits")
print("4 : Quitter")
reponse = input("-")
if reponse == '1':
return pharmacie.achat()
elif reponse == '2':
return pharmacie.approvisionnement()
elif reponse =='3':
return pharmacie.affichage()
elif reponse == '4':
return False
#La totalité du prorgamme tourne.. là-dedans
again = True
while again:
main()
J'attends impatiemment vos avis ou du moins la réponse à certaines de mes questions
Bienvenue au club ! Ton code est propre et lisible : bravo !
Quelques remarques que je m'étais faites en écrivant ma version en liaison avec tes questions :
Concernant la POO, cet exo est intéressant si on considère qu'on peut avoir plusieurs pharmacies à gérer : pourquoi pas puisqu'on a défini une classe Pharmacie ? Et des questions d'analyse du problème se posent ... Exemple sur les stocks de médocs : j'ai 3 pharmacies, est-ce que j'ai un seul stock pour les 3, ou un stock par pharmacie ? Au niveau programmation, la traduction est : est-ce que la variable liste_medicaments est globale (ou une variable de classe), ou est-ce une variable d'instance de la classe pharmacie ?
On peut aussi être un peu plus réaliste et se dire qu'on devrait avoir une base de médicaments commune (nom médoc, fournisseur, prix de base etc...) et gérer les quantités en stock localement dans chaque pharmacie. C'est le choix que j'ai fait dans ma version.
On peut avoir les mêmes questions pour les clients : base commune ou base locale ?
Coté programmation, comme l'accès se fait toujours par nom pour les médocs et les clients, j'ai choisi d'utiliser des dictionnaires plutôt que des listes ... ça facilite la vie
J'ai bien aimé ton exemple d'utilisation des properties : perso, je suis passé un peu à coté de cette possibilité car j'accède en direct par leur nom aux variables d'instance et je me fais confiance en tant que programmeur pour ne pas les modifier à tort et à travers. Donc pas de redifintion des __get__ et __set__ mais j'avoue que pour un module qui serait diffusé indépendamment, ton code est un bon exemple de vérouillage des accès
Enfin concernant la mise en fonction de code, du main() en particulier :
(une petite remarque, il semble manquer un again ligne 22 pour arrêter le programme :
again = True
while again :
again = main()
Perso, j'ai plutôt tendance à mettre en fonction un code utilisé une seule fois seulement pour des questions de lisibilité mais je n'ai pas de religion la-dessus. Par contre, la question des performance a été discutée dans un fil sur ce forum, et il apparaît qu'en Python (version 2 au moins), un bout de code est exécuté plutôt plus rapidement quand il est dans une fonction que dans le __main__ (pour une question d'allocation des variables si j'ai bien compris), donc si un bout de code est sur un chemin critique pour les performances, on aurait plutôt intérêt à le mettre en fonction !
Merci pour tes réponses et, en effet il manque un "again=", tu as l'oeil
Et c'est vrai que dans mon cas, avec une seule Pharmacie, toute la classe Pharmacie peut paraître assez superflus. Mais je me suis fait la remarque que ça peut être utile, comme tu dis, quand on rajoute des pharmacies supplémentaires.
Dans mon code, pour gérer ce cas, la solution la plus rapide (mais pas la plus évidente/compréhensible) serait de rajouter à chaque objet médicament une autre variable appelée "nom_pharmacie" (pour connaître la pharmacie à laquelle il appartient). Du coup on pourrait avoir dans la liste différents objets qui sont les mêmes médicaments mais qui n´appartiennent pas à la même pharmacie (et avec des stocks différents).
Je retiens également ton conseil, au niveau des performances, qui consiste à privilégier les fonctions plutot que des instructions dans __main__.
Et c'est également assez interessant de pouvoir comparer les différentes solutions possibles qui existent pour un même programme.
Dans mon code, pour gérer ce cas, la solution la plus rapide (mais pas la plus évidente/compréhensible) serait de rajouter à chaque objet médicament une autre variable appelée "nom_pharmacie" (pour connaître la pharmacie à laquelle il appartient). Du coup on pourrait avoir dans la liste différents objets qui sont les mêmes médicaments mais qui n´appartiennent pas à la même pharmacie (et avec des stocks différents).
Exact, mais ça ne va pas être facile de modifier ton stock pour une pharmacie donnée par ex. : tu vas devoir parcourir toute la liste liste_medicaments à la recherche d'un stock existant pour le modifier, sinon tu risques d'en créer un second pour la même pharmacie et le même médicament et bonjour la gestion des stocks !
C'est bien plus simple de laisser Python faire ça avec une variable d'instance. Voici la différence entre ce que j'appelle une variable de classe ('medocs') et une variable d'instance ('clients') à travers un exemple :
Quand je fais référence à ph1.medocs ou ph3.medocs, je fais référence à la même liste (variable de classe définie dans class).
Quand je fais référence à ph1.clients ou ph3.clients, ce sont deux listes différentes associées chacune à son instance ph1 ou ph3 (variable d'instance définie dans le def __init__ ) : du coup, c'est très facile de gérer une liste propre à chaque instance (pharmacie ici).
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.