Une condition qui renvoie sur une ligne de code

Bonjour.

Je suis débutant en Python, en train de me faire la main sur un petit programme de facturation. Et naturellement, j'ai un problème.

En simplifiant là où il se situe, dans une ligne de facturation, j'ai pour un produit :

ref
(référence),
puht
(prix unitaire hors taxes),
con
(conditionnement),
qte
(quantité) et
ptht
(prix total hors taxes).

Donc, à la base :

ref = str(input('Référence :'))
con = int(input('Conditionnement :'))
puht = float(input('Prix unitaire HT :'))
qte = float(input('Quantité :'))
ptht = puht * qte


Mais je dois tenir compte du conditionnement : la quantité saisie doit être un multiple.

Ce que j'essaie :

if qte % con != 0:
    print('La quantité doit être un multiple du conditionnement')
    # ??? qte ???
else:
    # ??? ptht ???


Si le reste de la division est égal à zéro, on passe au calcul du
ptht
, mais si il est différent, il faut saisir à nouveau la
qte
. Là je bloque, je ne connais pas l'instruction qui permet de remonter sur une ligne.

Merci.

15 réponses

  1. Même lorsque j'aurai assimilé tout ça, dans l'état actuel, ça me semble très confus. Les préfixes que j'avais mis sont une habitude qui me vient des bases de données afin de bien séparer les items. Par exemple, pour le prix d'un produit, je choisis :

    - PRO_PUHT dans la table T_PRODUITS.
    - FAC_PUHT (et FAC_QTE, entre autre) dans la table T_VENTES_SUB

    Données ensuite envoyées dans la requête pour les calculs.

    Bref, comme je songe intégrer tout ça dans une base de données (bien que je n'en sois pas encore là), j'ai pris les devants en renommant les items à ma manière habituelle...
    0
    1. Modérateur
      Ah ok, en fait c'est juste que les objets font naturellement le travail de "regroupement" que tu faisais avec des préfixes
      pro_
      et
      fac_
      . Tu peux voir un objet comme une sorte de tuple typé, dont chaque élément est accédé par un nom dédié.

      Voici un exemple simple d'objet :

      class Personne:
          def __init__(self, prenom, nom):
              self.prenom = prenom
              self.nom = nom
          def dit(self, message):
              print(f"{self.prenom} {self.nom} dit {message}")
      
      p = Personne("Albert", "Einstein") # p est initialié conformément à Personne.__init__
      print(p.nom)
      print(p.prenom)
      p.dit("bonjour") # Albert Einstein dit bonjour
      • Personne
        correspond à une classe (ou objet) ;
      • p
        correspond à une instance de
        Personne
        .
      • nom
        et
        prenom
        sont des attributs de
        Personne
        .


      Quand tu déclares un objet, l'instance à laquelle s'applique une méthode est noté
      self
      désigne l'instance courante (e.g.
      p
      ).

      Si tu as compris ça tu as compris l'essentiel et le code que je t'ai partagé devrait être assez clair.

      L'avantage des objets (outre le fait qu'ils rendent le code mieux organisé et plus clair), c'est qu'on peut réutiliser des objets pour en définir d'autres (soit en tant qu'attribut, comme j'ai fait pour
      Bill
      , soit par héritage, comme j'ai fait pour
      OrderedProduct
      ).

      Mais bref, si tu ne te sens pas d'utiliser des objets, continue avec ton code :-)

      Bonne chance
      0
      1. C'est avec les objets que je vais commencer à m'y perdre ! Ça devient vraiment complexe et il me faut le temps de digérer...
        0
        1. Modérateur
          Bonjour,

          Je pense qu'il est temps de commencer à faire des objets si tu commences à t'y perdre. Voici ce que je te propose :

          def input_cast(label = "", cast = lambda x: x, check = lambda: True):
              while True:
                  try:
                      ret = cast(input(label))
                      if check(ret):
                          return ret
                      else:
                          print('Valeur invalide !')
                  except ValueError:
                      pass
          
          def check_positive(x):
              return x > 0
          
          class Product:
              def __init__(self, ref, des, con, puht, tva_c):
                  self.ref = ref
                  self.des = des
                  self.con = con
                  self.puht = puht
                  self.tva_c = tva_c
          
          class OrderedProduct(Product):
              def __init__(self, ref, des, con, puht, tva_c, qte, rab_t):
                  super().__init__(ref, des, con, puht, tva_c)
                  self.qte = qte
                  self.rab_t = rab_t
                  self.rab = self.calcul_rab()
                  self.ptht = self.calcul_ptht()
                  
              def calcul_rab(self):
                  return round(self.puht * (self.rab_t / 100), 2)
              
              def calcul_ptht(self):
                  return round((self.puht - self.rab) * self.qte, 2)
          
          def prompt_ordered_product():
              ref = input('Référence : ')
              des = input('Désignation : ')
              con = input_cast('Conditionnement : ', int, check_positive)
              puht = input_cast('Prix unitaire HT : ', float, check_positive)
              tva_c = input_cast('Code TVA : ', int, check_positive)
              qte = input_cast('Quantité : ', float, check_positive)
          
              while qte % con != 0:
                  print('La quantité saisie doit être un multiple de', con)
                  qte = input_cast('Quantité : ', float, check_positive)
          
              rab_t = float(input('Rabais (%) : '))
              return OrderedProduct(ref, des, con, puht, tva_c, qte, rab_t)
          
          class Billing:
              def __init__(self, tht, rem_t, esc_t, fdp, fde):
                  self.tht = tht
                  self.rem_t = rem_t
                  self.esc_t = esc_t
                  self.fdp = fdp
                  self.fde = fde
                  self.rem = round(self.tht * (self.rem_t / 100), 2)
                  self.mnc = round(self.tht - self.rem, 2)
                  self.esc = round(self.mnc * (esc_t / 100), 2)
                  self.mnht = round(self.mnc - self.esc, 2)
                  self.tnht = round(self.mnht + self.fdp + self.fde, 2)
                  self.tva = round(self.tnht * 0.2, 2)
                  self.tttc = round(self.tnht + self.tva, 2)
                  
          def prompt_billing(tht):
              rem_t = input_cast('Remise (%) : ', float, check_positive)
              esc_t = input_cast('Escompte au règlement (%) : ', float, check_positive)
              fdp = input_cast('Frais de port : ', float, check_positive)
              fde = input_cast('Frais d\'emballage : ', float, check_positive)
              return Billing(tht, rem_t, esc_t, fdp, fde)
          
          class Bill:
              def __init__(self, ordered_products, billing):
                  self.ordered_products = ordered_products
                  self.billing = billing
              def __str__(self):
                  s = f"""Total HT : {self.billing.tht}
          ------------------------------------------------------------------------------------------------------
           Réf      | Désignation                |   Cond. |     PU HT | TVA |   Rabais |       Qte |     PT HT
          ------------------------------------------------------------------------------------------------------"""
                  
                  for pro in self.ordered_products:
                      s += f' {pro.ref:11}{pro.des:27}{pro.con:>9}{pro.puht:>12.2f}{pro.tva_c:>6}{pro.rab:>11.2f}{pro.qte:>12.2f}{pro.ptht:>12.2f}\n'
          
                  s += f"""------------------------------------------------------------------------------------------------------
                  
          Total HT :\t\t\t{self.billing.tht:>12.2f}
          .....................................................................................................
          Remise :\t\t\t{self.billing.rem:>12.2f}
          Montant net commercial :\t{self.billing.mnc:>12.2f}
          ......................................................................................................
          Escompte au règlement :\t\t{self.billing.esc:>12.2f}
          Montant net HT :\t\t{self.billing.mnht:>12.2f}
          ......................................................................................................
          Frais de port :\t\t\t{self.billing.fdp:>12.2f}
          Frais d\'emballage :\t\t{self.billing.fde:>12.2f}
          Total net HT :\t\t\t{self.billing.tnht:>12.2f}
          ......................................................................................................
          TVA :\t\t\t\t{self.billing.tva:>12.2f}
          ......................................................................................................
          Total TTC :\t\t\t{self.billing.tttc:>12.2f}"""
                  return s
              
          def main():
              tht = 0
              ordered_products = list()
              while True:
                  pro = prompt_ordered_product()
                  ordered_products.append(pro)
                  print('Prix total HT : ', pro.ptht)
                  tht += pro.ptht
                  continuer = input('Saisie terminée (o/n)')
                  if continuer == 'o':
                      break
              billing = prompt_billing(tht)
              bill = Bill(ordered_products, billing)
              print(bill)
              
          main()
          


          Bonne chance
          0
          1. Alors voilà où j'en suis...

            1) J'ai renommé les entrées à ma convenance, séparant produit (prefixe pro_) et facturation (préfixe fac_) afin de m'y retrouver plus facilement pour la suite.

            2) J'ai rajouté deux entrées pour le produit : la désignation et le code TVA (1, taux réduit ; 2, taux normal). Maintenant que je connais la façon de faire (enfin j'espère !), je vais modifier l'ensemble pour séparer les produits selon leur code TVA.

            3) J'ai ajouté tout ce qu'il y a après le Total Hors Taxes.

            4) Enfin, là où j'ai encore un problème, c'est dans l'affichage final (voir code). S'affiche sur une ligne tous les éléments de la facture. Problème : si je facture au moins 2 produits, seul le dernier s'affiche (néanmoins, les résultats des calculs ne sont pas affectés).

            def input_cast(label = "", cast = lambda x: x, check = lambda: True):
                while True:
                    try:
                        ret = cast(input(label))
                        if check(ret):
                            return ret
                        else:
                            print('Valeur invalide !')
                    except ValueError:
                        pass
            
            def check_positive(x):
                return x > 0
            
            def prompt_produits():
                pro_ref = input('Référence : ')
                pro_des = input('Désignation : ')
                pro_con = input_cast('Conditionnement : ', int, check_positive)
                pro_puht = input_cast('Prix unitaire HT : ', float, check_positive)
                pro_tva_c = input_cast('Code TVA : ', int, check_positive)
                fac_qte = input_cast('Quantité : ', float, check_positive)
            
                while fac_qte % pro_con != 0:
                    print('La quantité saisie doit être un multiple de', pro_con)
                    fac_qte = input_cast('Quantité : ', float, check_positive)
            
                fac_rab_t = float(input('Rabais (%) : '))
                return (pro_ref, pro_des, pro_con, pro_puht, pro_tva_c, fac_qte, fac_rab_t)
            
            def calcul_rab(pro_puht, fac_rab_t):
                return round(pro_puht * (fac_rab_t / 100), 2)
            
            def calcul_ptht(pro_puht, fac_rab, fac_qte):
                return round((pro_puht - fac_rab) * fac_qte, 2)
            
            fac_tht = 0
            
            while True:
                (pro_ref, pro_des, pro_con, pro_puht, pro_tva_c, fac_qte, fac_rab_t) = prompt_produits()
                fac_rab = calcul_rab(pro_puht, fac_rab_t)
                fac_ptht = calcul_ptht(pro_puht, fac_rab, fac_qte)
                print('Prix total HT : ', fac_ptht)
                fac_tht += fac_ptht
                continuer = input('Saisie terminée (o/n)')
                if continuer == 'o':
                    break
            print('Total HT : ', fac_tht)
            
            fac_rem_t = float(input('Remise (%) : '))
            fac_esc_t = float(input('Escompte au règlement (%) : '))
            fac_fdp = float(input('Frais de port : '))
            fac_fde = float(input('Frais d\'emballage : '))
            
            fac_rem = round(fac_tht * (fac_rem_t / 100), 2)
            fac_mnc = round(fac_tht - fac_rem, 2)
            fac_esc = round(fac_mnc * (fac_esc_t / 100), 2)
            fac_mnht = round(fac_mnc - fac_esc, 2)
            fac_tnht = round(fac_mnht + fac_fdp + fac_fde, 2)
            fac_tva = round(fac_tnht * 0.2, 2)
            fac_tttc = round(fac_tnht + fac_tva, 2)
            
            print('------------------------------------------------------------------------------------------------------')
            print(' Réf      | Désignation                |   Cond. |     PU HT | TVA |   Rabais |       Qte |     PT HT ')
            print('------------------------------------------------------------------------------------------------------')
            print (f' {pro_ref:11}{pro_des:27}{pro_con:>9}{pro_puht:>12.2f}{pro_tva_c:>6}{fac_rab:>11.2f}{fac_qte:>12.2f}{fac_ptht:>12.2f}')
            print('\n------------------------------------------------------------------------------------------------------\n')
            print(f'Total HT :\t\t\t{fac_tht:>12.2f}')
            print('......................................................................................................')
            print(f'Remise :\t\t\t{fac_rem:>12.2f}')
            print(f'Montant net commercial :\t{fac_mnc:>12.2f}')
            print('......................................................................................................')
            print(f'Escompte au règlement :\t\t{fac_esc:>12.2f}')
            print(f'Montant net HT :\t\t{fac_mnht:>12.2f}')
            print('......................................................................................................')
            print(f'Frais de port :\t\t\t{fac_fdp:>12.2f}')
            print(f'Frais d\'emballage :\t\t{fac_fde:>12.2f}')
            print(f'Total net HT :\t\t\t{fac_tnht:>12.2f}')
            print('......................................................................................................')
            print(f'TVA :\t\t\t\t{fac_tva:>12.2f}')
            print('......................................................................................................')
            print(f'Total TTC :\t\t\t{fac_tttc:>12.2f}')
            0
            1. Modérateur
              Bonjour,

              Pour vérifier si les valeurs saisies vérifient une certaine propriété (par exemple, s'agit-il d'une valeur positive), tu peux compléter
              input_cast
              en lui passant en paramètre optionnel une fonction (que je nomme ci-dessous
              check_positive
              ) qui va vérifier si cette propriété est vérifié.

              Concernant le calcul de la somme des ptht, il suffit de créer une variable que tu vas incrémenter à chaque tour de boucle avec le ptht calculé.

              def input_cast(label = "", cast = lambda x: x, check = lambda: True):
                  while True:
                      try:
                          ret = cast(input(label))
                          if check(ret):
                              return ret
                          else:
                              print("Valeur invalide!")
                      except ValueError:
                          pass
              
              def check_positive(x):
                  return x > 0
              
              def prompt_product():
                  reference = input('Référence :')
                  conditionnement = input_cast('Conditionnement :', int, check_positive)
                  puht = input_cast('Prix unitaire HT :', float, check_positive)
                  quantite = input_cast('Quantité :', float, check_positive)
              
                  while quantite % conditionnement != 0:
                      print('La quantité saisie doit être un multiple du conditionnement.')
                      qte = input('Quantité :', float, check_positive)
              
                  taux_rabais = input_cast('Rabais (%) :', float, check_positive)
                  return (reference, conditionnement, puht, quantite, taux_rabais)
              
              def compute_rab(puht, taux_rabais):
                  return round(puht * (taux_rabais / 100))
              
              def compute_ptht(puht, rabais, quantite):
                  return round((puht - rabais) * quantite, 2)
              
              ptht_total = 0
              while True:
                  (reference, conditionnement, puht, quantite, taux_rabais) = prompt_product()
                  rabais = compute_rab(puht, taux_rabais)
                  ptht = compute_ptht(puht, rabais, quantite)
                  print('Prix total HT :', ptht)
                  ptht_total += ptht
                  continuer = input("Saisie terminée (o/n)")
                  if continuer == "o":
                      break
              print("Total des PTHT", ptht_total)


              Ensuite si tu veux aller plus loin, il faudrait probablement créer une classe qui stocke chaque produit (
              class Product
              ) et dont la définition dépend de ce qui caractérise un Produit. De la même manière, tu pourrais avoir un objet
              Ordering
              qui concerne un
              Product
              , une quantité, et un calcul de rabais. Ensuite, tu peux imaginer demander la saisie de tes produits dans un premier temps, puis celles de tes commandes dans un second temps.

              Bonne chance
              0
              1. Eh bien toujours merci... C'est donc avec le += qu'on cumule les montants et préalablement en déclarant le total à zéro. Là j'ai juste enlevé le check_positive au rabais (dans la réalité, le nombre de produits proposés au rabais est très minoritaire).

                Je vais étudier tout ça avec attention (surtout les deux premières fonctions) et je passerai à la suite un peu plus tard. Dans mon idée je voulais faire les choses en trois temps : la partie de base, fonctions, calculs ; intégrer les produits dans une liste pour ne plus avoir à taper que la référence (puisque dans la réalité, il y a d'autres colonnes) ; et enfin, les intégrer dans une base de données (domaine où je suis nettement plus à l'aise).

                Merci.
                0
              2. Modérateur
                @NervaC'est donc avec le += qu'on cumule les montants et préalablement en déclarant le total à zéro.

                Effectivement tu peux utiliser
                x += n
                qui est équivalent à
                x = x + n
                .
                • De même, les opérateurs
                  -=
                  ,
                  *=
                  ,
                  /=
                  ,
                  %=
                  ,
                  |=
                  ,
                  &=
                  correspondent aux opérateurs
                  -
                  (soustraction),
                  *
                  (multiplication),
                  /
                  (division),
                  %=
                  (modulo),
                  |=
                  (ou logique),
                  &=
                  (et logique).
                • Certains langages, comme le Java et le C++ mettent aussi à disposition
                  x++
                  et
                  x--
                  , qui signifient respectivement
                  x += 1
                  et
                  x -= 1
                  mais ils n'existent pas en python.


                Dans mon idée je voulais faire les choses en trois temps : la partie de base, fonctions, calculs ; intégrer les produits dans une liste pour ne plus avoir à taper que la référence (puisque dans la réalité, il y a d'autres colonnes) ;

                Note que l'opérateur
                +
                permet de concaténer deux listes (tu as donc ici aussi un opérateur
                +=
                ), et sinon tu peux utiliser la méthode
                append
                pour ajouter un élément en fin de liste. Au sens base de données, cette liste correspond plus ou moins au contenu d'une table.

                et enfin, les intégrer dans une base de données (domaine où je suis nettement plus à l'aise).

                Si tu es plus à l'aise avec les bases de données, dis-toi que les objets python qu'il faudrait déclarer correspondent plus ou moins aux tables de ta base de données. Chaque instance d'un objet correspond à un enregistrement au sens base de donnée.

                Bonne chance
                0
            2. Là ça avance bien. Maintenant la suite sera de trouver la fonction qui permette de totaliser les ptht de chaque ligne dans le tht.

              J'ai compris que le imput_cast interdit les saisies non conformes. Par contre, il semble y avoir un conflit avec while quantite % conditionnement != 0: puisque ça plante au niveau de la quantité si elle n'est pas un multiple du conditionnement.

              Merci encore...
              0
              1. Là déjà merci, je commence à voir comment tout cela se structure...

                J'ai corrigé la parenthèse et j'ajouterai dorénavant le formatage du code en python.

                Le rabais est une réduction accordée pour un produit selon son état. Par exemple, un lot de flacons où l'étiquette serait collée de travers est proposée avec un rabais de 10 %.

                Dans le but de simplifier, j'ai compliqué tout. Il y a le taux de rabais en % (t_rab), celui qu'on saisit dans la facture, et le montant du rabais (rab), qui est calculé.

                rab = puht*(t_rab/100)
                ptht = (puht-rab)*qte


                J'ai modifié le code mais j'ai fait une erreur quelque part puisqu'il y a un message après la saisie de t_rab :

                def saisie():
                    ref = str(input('Référence :'))
                    con = int(input('Conditionnement :'))
                    puht = float(input('Prix unitaire HT :'))
                    qte = float(input('Quantité :'))
                
                    while qte % con != 0:
                        print('La quantité saisie doit être un multiple du conditionnement.')
                        qte = float(input('Quantité :'))
                
                    t_rab = float(input('Rabais (%) :'))
                    return (ref, con, puht, qte, t_rab)
                
                def rab(puht, t_rab):
                    return round(puht*(t_rab/100))
                
                def ptht(puht, rab, qte):
                    return round((puht - rab) * qte, 2)
                
                for _ in range(5): # Saisir 5 produits
                    (ref, con, puht, qte, t_rab) = saisie()
                    x = ptht(puht, rab, qte)
                    print('Prix total HT :', x)


                En ce qui concerne le contrôle de la saisie, je verrai par la suite comment implanter des "gardes-fous" (je ne pense pas que ça soit le plus compliqué). Par contre, avec un un range de 5, ça oblige à saisir 5 produits alors que le nombre sera toujours variable selon la liste des produits disponibles et la commande qui est faite.
                0
                1. Modérateur
                  Bonjour,

                  C'est parce que par endroit dans ton code tu confonds la fonction
                  rab
                  et la valeur
                  t_rab
                  . Du coup tu te retrouves à impliquer une fonction dans un calcul numérique, d'où l'erreur. Voici à quoi pourrait ressembler ton programme une fois corrigé.

                  def saisie():
                      ref = str(input('Référence :'))
                      con = int(input('Conditionnement :'))
                      puht = float(input('Prix unitaire HT :'))
                      qte = float(input('Quantité :'))
                  
                      while qte % con != 0:
                          print('La quantité saisie doit être un multiple du conditionnement.')
                          qte = float(input('Quantité :'))
                  
                      t_rab = float(input('Rabais (%) :'))
                      return (ref, con, puht, qte, t_rab)
                  
                  def rab(puht, t_rab):
                      return round(puht * (t_rab / 100))
                  
                  def ptht(puht, rab, qte):
                      return round((puht - rab) * qte, 2)
                  
                  for _ in range(5): # Saisir 5 produits
                      (ref, con, puht, qte, t_rab) = saisie()
                      rabais = rab(puht, t_rab)
                      x = ptht(puht, rabais, qte)
                      print('Prix total HT :', x)    


                  Personnellement, je te conseille pour éviter toute confusion de mettre un verbe dans tes noms de fonctions. Si on fait le parallèle avec la grammaire française, vois un peu les variables comme des noms et des adjectifs, et vois les fonctions comme des verbes. De la même manière, je te recommande d'avoir des noms de variables parlants (les abréviations rendent le code dur à relire quelques mois plus tard :p).

                  Concernant le nombre de produit, ici on a effectivement mis 5 en dur. Tout dépend de ce que tu veux faire. Si tu as une liste de produit, tu peux remplacer 5 par la longueur de ce catalogue. Si tu n'as pas de catalogue et que le but de ton programme est de le peupler, tu peux remplacer la boucle
                  for
                  par un
                  while True ...
                  que tu interrompras quand l'utilisateur le décidera (quitte à poser une question supplémentaire du genre "Saisir un autre produit ? (o/n)").

                  Une fois remis en forme, ton code pourrait par exemple ressembler à ceci :

                  def input_cast(label = "", cast = lambda x: x):
                      while True:
                          try:
                              return cast(input(label))
                          except ValueError:
                              pass
                  
                  def prompt_product():
                      reference = input('Référence :')
                      conditionnement = input_cast('Conditionnement :', int)
                      puht = input_cast('Prix unitaire HT :', float)
                      quantite = input_cast('Quantité :', float)
                  
                      while quantite % conditionnement != 0:
                          print('La quantité saisie doit être un multiple du conditionnement.')
                          qte = input('Quantité :', float)
                  
                      taux_rabais = input_cast('Rabais (%) :', float)
                      return (reference, conditionnement, puht, quantite, taux_rabais)
                  
                  def compute_rabais(puht, taux_rabais):
                      return round(puht * (taux_rabais / 100))
                  
                  def compute_ptht(puht, rabais, quantite):
                      return round((puht - rabais) * quantite, 2)
                  
                  while True:
                      (reference, conditionnement, puht, quantite, taux_rabais) = prompt_product()
                      rabais = compute_rabais(puht, taux_rabais)
                      ptht = compute_ptht(puht, rabais, quantite)
                      print('Prix total HT :', ptht)
                      continuer = input("Saisie terminée (o/n)")
                      if continuer == "o":
                          break


                  Bonne chance
                  0
              2. Modérateur
                Bonjour à tous,

                @Tous

                J'ai corrigé vos messages pour utiliser la coloration syntaxique. Pour l'utiliser cliquez à côté du triangle à côté du bouton code. Plus de détails dans ce tutoriel ou en modifiant l'un de vos anciens messages.

                @Nerva, message #12

                qu'appelles-tu
                rab
                ? Note que dans ta fonction il manque une parenthèse ouvrante.

                def saisie():
                    ref = str(input('Référence :'))
                    con = int(input('Conditionnement :'))
                    puht = float(input('Prix unitaire HT :'))
                    qte = float(input('Quantité :'))
                
                    while qte % con != 0:
                        print('La quantité saisie doit être un multiple du conditionnement.')
                        qte = float(input('Quantité :'))
                
                    rab = float(input("Rab :"))
                    return (ref, con, puht, qte, rab)
                
                def ptht(puht, rab, qte):
                    return round((puht - rab) * qte, 2)
                
                for _ in range(5): # Saisir 5 produits
                    (ref, con, puht, qte, rab) = saisie()
                    x = ptht(puht, rab, qte)
                    print('Prix total HT :', x)


                Note qu'il faudrait sans doute contrôler dans saisie avec des boucles while que les valeurs saisies sont des entiers positifs. Note aussi que convertir une saisie en entier peut échouer si la chaîne n'est pas un texte correspondant à une valeur entière. Dans ce cas python lèvera une exception, que tu peux rattraper (par exemple, en vue de re-demander une valeur correcte.

                def input_cast(label = "", cast = lambda x: x):
                    while True:
                        try:
                            return cast(input(label))
                        except ValueError:
                            pass
                
                i = input_cast("Saisir un entier", int)
                x = input_cast("Saisir un réel", float)


                Bonne chance
                0
                1. De retour...

                  Alors j'ai créé la fonction qui calcule le prix total hors taxes (donc, somme de chaque ligne) :

                  def ptht(puht, rab, qte):
                      return round(puht - rab) * qte, 2)


                  Mais je ne sais ni où la placer ni comment l'utiliser...
                  0
                  1. Phil_1857, même réponse : je suis débutant et c'est pour le moment compliqué...
                    0
                    1. je te conseille le site http://www.france-ioi.org/

                      il y a une approche pas à pas, niveau par niveau

                      les énoncés sont donnée de façon rigolote avec des "extraterrestres" et compagnie

                      tu peux progresser vite la dessus, les leçons sont bien expliquées
                      0
                  2. Bonsoir,

                    Peut-être en mettant tout ça dans une boucle
                    while(True):
                    et en faisant un
                    break
                    pour sortir si
                    ref == 'quitter'
                    .
                    0
                    1. Écraser l'ancienne valeur, ok, mais si il y avait plusieurs entrées à "dédoubler", ça finirait par faire fouillis, non ?

                      ---

                      Jusque là tout allait bien mais je m'arrache les cheveux sur la suite car je suis limité à un seul produit. Après avoir validé la quantité et calculé le
                      ptht
                      , je dois pouvoir "remonter" pour facturer un second (ou plus) article et au final, sommer le
                      ptht
                      de chacun dans le
                      tht
                      (total hors taxes) avant de passer à la suite de la facture (qui là ne pose pas de soucis). Je suppose qu'il faut aussi utiliser une boucle
                      while
                      mais je ne sais pas du tout comment faire ça.

                      ref = str(input('Référence :'))
                      con = int(input('Conditionnement :'))
                      puht = float(input('Prix unitaire HT :'))
                      qte = float(input('Quantité :'))
                      
                      while qte % con != 0:
                          print('La quantité saisie doit être un multiple du conditionnement.')
                          qte = float(input('Quantité :'))
                      
                      ptht = puht * qte
                      print('Prix total HT :',round(ptht, 2))
                      
                      # (??? tht = somme des ptht ???)
                      0
                      1. Il te suffit de créer une fonction qui englobe le code qui existe déjà et tu pourras l'appeler 2 fois pour les 2 produits différents.

                        Tu n'auras plus qu'à sommer le résultat des 2 fonctions

                        En python pour créer une fonction :

                        def nomFonction(paramètresProduit):
                            # ton code
                            return ptht # la valeur retournée par la fonction
                        
                        ptht1 = nomFonction(argumentsProduit1)
                        ptht2 = nomFonction(argumentsProduit2)
                        
                        # Il est possible de sauter l'étape au-dessus et de directement 
                        # additionner nomFonction(...) qui contient la valeur retournée
                        
                        somme = ptht1 + ptht2


                        Je te laisse te renseigner sur ce qu'est un paramètre et un argument pour une fonction, tu en auras peut-être besoin si les caractéristiques changent sinon tu pourras laisser vide les parenthèses

                        Sinon, plutôt que d'utiliser une fonction, tu peux aussi utiliser une boucle
                        for
                        englobant tout ton code pour forcer la répétition x fois mais ensuite ça t'oblige à utiliser une liste pour pouvoir différencier les 2
                        ptht
                        .
                        0
                      2. @urilou777Oui j'ai pensé à une fonction mais je débute. J'ai déjà un peu bidouillé pour me faire la main avec celle-ci (qui n'a rien à voir avec le sujet) :

                        # Calcul de l'hypoténuse
                        import math
                        
                        def hypotenuse(l, h):
                         return round(math.sqrt(l**2+h**2), 2)
                        
                        l = float(input('Largeur :'))
                        h = float(input('Hauteur :'))
                        
                        print('Hypoténuse :', hypotenuse(l, h))


                        Seulement, si je vois à peu près comment structurer la fonction adéquate, à mon niveau je suis incapable de l'intégrer dans le code. D'autant plus qu'il risque d'y avoir plus de deux produits.
                        0
                      3. Méthode non-conseillée avec for et liste, sachant qu'il y a d'autres façon d'écrire la même chose
                        # déclaration de la liste pour différencier les 2 valeurs 
                        # et ne pas écraser quand on passe au deuxième produit
                        ptht = []
                        
                        for x in range(2):
                            # ton code ici
                            ptht[x] = puht * qte # on accède au "x-ième" élément de la liste
                            print('Prix total HT :',round(ptht[x], 2))
                        
                        tht = ptht[0] + ptht[1]
                        0
                      4. @NervaTu t'en fiches du nombre de produits. Si tes produits sont référencés de la même manière, disons par exemple un nom, un prénom et un poids par exemple. tu peux créer une et une seule fonction que tu appelleras autant de fois que tu veux.

                        Vu que l'utilisateur rentre manuellement à chaque fois (avec
                        input
                        ) les valeurs, et qu'elles n'existent pas déjà dans des variables de ton code, tu n'as même pas besoin de paramètre/argument.

                        Là, ça revient quasiment juste à mettre tout ton code dans une fonction, quasi rien d'autre à faire mais renseignes-toi bien sûr ce que c'est une fonction et toute la terminologie qui va avec.

                        Il suffit de stocker le résultat (
                        return
                        ) dans une variable différente à chaque fois pour ne pas "écraser". et il est aussi possible d'appeler une fonction avec une boucle for :
                        0
                    2. Oui là ça fait le travail comme il faut. Merci...

                      J'avais pensé à une boucle mais je me demandais si c'était bien conforme de définir deux fois
                      qte = float(input('Quantité :'))
                      0
                      1. C'est tout à fait possible, ça va venir écraser l'ancienne valeur.
                        0
                    3. L'instruction GOTO n'existe pas nativement en Python, faut utiliser des combines

                      Plutôt que de se compliquer la vie je te suggère une structure du type

                      qte = float(input('Quantité :'))
                      tant que qte % con != 0
                          print('La quantité doit être un multiple du conditionnement')
                          qte = float(input('Quantité :'))
                      ptht = puht * qte


                      Au lieu du
                      if
                      qui ne s'exécute qu'une seule fois, il te faut une boucle
                      while
                      car, je suppose que tu ne peux pas anticiper le nombre de mauvaises saisies qu'il y aura...
                      0