Introduction au langage Python par l'exemple


précédentsommairesuivant

V. Exercice d'application - [IMPÔTS]

Image non disponible

V-A. Le problème

On se propose d'écrire un programme permettant de calculer l'impôt d'un contribuable. On se place dans le cas simplifié d'un contribuable n'ayant que son seul salaire à déclarer :

  • on calcule le nombre de parts du salarié nbParts=nbEnfants/2 +1 s'il n'est pas marié, nbEnfants/2+2 s'il est marié, où nbEnfants est son nombre d'enfants ;
  • on calcule son revenu imposable R=0.72*S où S est son salaire annuel ;
  • on calcule son coefficient familial Q=R/N ;
  • on calcule son impôt I d'après les données suivantes
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
12620.0 0 0
13190 0.05 631
15640 0.1 1290.5
24740 0.15 2072.5
31810 0.2 3309.5
39970 0.25 4900
48360 0.3 6898.5
55790 0.35 9316.5
92970 0.4 12106
127860 0.45 16754.5
151250 0.50 23147.5
172040 0.55 30710
195000 0.60 39312
0 0.65 49062

Chaque ligne a trois champs. Pour calculer l'impôt I, on recherche la première ligne où QF<=champ1. Par exemple, si QF=30000 on trouvera la ligne :

24740 0.15 2072.5

L'impôt I est alors égal à 0.15*R - 2072.5*nbParts. Si QF est tel que la relation QF<=champ1 n'est jamais vérifiée, alors ce sont les coefficients de la dernière ligne qui sont utilisés. Ici :

0 0.65 49062

ce qui donne l'impôt I=0.65*R - 49062*nbParts.

V-B. Version avec listes

Programme (impots_01)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
# -*- coding=utf-8 -*-

import math, sys

def cutNewLineChar(ligne):
    # on supprime la marque de fin de ligne si elle existe
    l=len(ligne);
    while(ligne[l-1]=="\n" or ligne[l-1]=="\r"):
        l-=1
    return(ligne[0:l]);

  # --------------------------------------------------------------------------
def calculImpots(marie,enfants,salaire,limites,coeffR,coeffN):
    # marié : oui, non
    # enfants : nombre d'enfants
    # salaire : salaire annuel

    # nombre de parts
    marie=marie.lower()
    if(marie=="oui"):
        nbParts=float(enfants)/2+2
    else:
        nbParts=float(enfants)/2+1
    # une 1/2 part de plus si au moins 3 enfants
    if enfants>=3:
        nbParts+=0.5
    # revenu imposable
    revenuImposable=0.72*salaire
    # quotient familial
    quotient=revenuImposable/nbParts
    # est mis à la fin du tableau limites pour arrêter la boucle qui suit
    limites[len(limites)-1]=quotient
    # calcul de l'impôt
    i=0
    while(quotient>limites[i]):
        i=i+1
    # du fait qu'on a placé quotient à la fin du tableau limites, la boucle précédente
    # ne peut déborder du tableau limites
    # maintenant on peut calculer l'impôt
    return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])


# ------------------------------------------------ main
# définition des constantes
DATA="data.txt"
RESULTATS="resultats.txt"
limites=[12620,13190,15640,24740,31810,39970,48360,55790,92970,127860,151250,172040,195000,0]
coeffR=[0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65]
coeffN=[0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5,12106,16754.5,23147.5,30710,39312,49062]

# lecture des données
try:
    data=open(DATA,"r")
except:
    print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
    sys.exit()

# ouverture fichier des résultats
try:
    resultats=open(RESULTATS,"w")
except:  
    print "Impossible de creer le fichier des résultats [RESULTATS]"
    sys.exit()

# on exploite la ligne courante du fichier des données
ligne=data.readline()
while(ligne != ''):
    # on enlève l'éventuelle marque de fin de ligne
    ligne=cutNewLineChar(ligne)
    # on récupère les 3 champs marié:enfants:salaire qui forment la ligne
    (marie,enfants,salaire)=ligne.split(",")
    enfants=int(enfants)
    salaire=int(salaire)
    # on calcule l'impôt
    impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
    # on inscrit le résultat
    resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
    # on lit une nouvelle ligne
    ligne=data.readline()
# on ferme les fichiers
data.close()
resultats.close()

Résultats

Le fichier des données data.txt
Sélectionnez
1.
2.
3.
4.
5.
6.
oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000
Le fichier resultats.txt des résultats obtenus
Sélectionnez
1.
2.
3.
4.
5.
6.
oui:2:200000:22504.0
non:2:200000:33388.0
oui:3:200000:16400.0
non:3:200000:22504.0
oui:5:50000:0.0
non:0:3000000:1354938.0

V-C. Version avec fichiers texte

Dans l'exemple précédent, les données nécessaires au calcul de l'impôt avaient été trouvées dans trois listes. Elles seront désormais cherchées dans un fichier texte :

 
Sélectionnez
1.
2.
3.
12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062
Programme (impots_02)
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
# -*- coding=utf-8 -*-

import math,sys

# --------------------------------------------------------------------------
def getTables(IMPOTS):
    # IMPOTS : le nom du fichier contenant les données des tables limites, coeffR, coeffN
    # le fichier IMPOTS existe-t-il ?
    try:
        data=open(IMPOTS,"r")
    except:
        return ("Le fichier IMPOTS n'existe pas",0,0,0)
    # création des 3 listes - on suppose que les lignes sont syntaxiquement correctes
    # -- ligne 1
    ligne=data.readline()
    if ligne== '':
        return ("La  ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
    limites=cutNewLineChar(ligne).split(":")
    for i in range(len(limites)):
        limites[i]=int(limites[i])
    # -- ligne 2
    ligne=data.readline()
    if ligne== '':
        return ("La  ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
    coeffR=cutNewLineChar(ligne).split(":")
    for i in range(len(coeffR)):
        coeffR[i]=float(coeffR[i])
    # -- ligne 3
    ligne=data.readline()
    if ligne== '':
        return ("La  ligne du fichier {0} est absente".format(IMPOTS),0,0,0)
    coeffN=cutNewLineChar(ligne).split(":")
    for i in range(len(coeffN)):
        coeffN[i]=float(coeffN[i])
    # fin
    return ("",limites,coeffR,coeffN)

# --------------------------------------------------------------------------
def cutNewLineChar(ligne):
    # on supprime la marque de fin de ligne si elle existe
    l=len(ligne);
    while(ligne[l-1]=="\n" or ligne[l-1]=="\r"):
        l-=1
    return(ligne[0:l]);

  # --------------------------------------------------------------------------
def calculImpots(marie,enfants,salaire,limites,coeffR,coeffN):
    # marié : oui, non
    # enfants : nombre d'enfants
    # salaire : salaire annuel

    # nombre de parts
    marie=marie.lower()
    if(marie=="oui"):
        nbParts=float(enfants)/2+2
    else:
        nbParts=float(enfants)/2+1
    # une 1/2 part de plus si au moins 3 enfants
    if enfants>=3:
        nbParts+=0.5
    # revenu imposable
    revenuImposable=0.72*salaire
    # quotient familial
    quotient=revenuImposable/nbParts
    # est mis à la fin du tableau limites pour arrêter la boucle qui suit
    limites[len(limites)-1]=quotient
    # calcul de l'impôt
    i=0
    while(quotient>limites[i]):
        i=i+1
    # du fait qu'on a placé quotient à la fin du tableau limites, la boucle précédente
    # ne peut déborder du tableau limites
    # maintenant on peut calculer l'impôt
    return math.floor(revenuImposable*coeffR[i]-nbParts*coeffN[i])


# ------------------------------------------------ main
# définition des constantes
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"

# les données nécessaires au calcul de l'impôt ont été placées dans le fichier IMPOTS
# à raison d'une ligne par tableau sous la forme
# val1:val2:val3...
(erreur,limites,coeffR,coeffN)=getTables(IMPOTS)

# y a-t-il eu une erreur ?
if(erreur):
    print "{0}\n".format(erreur)
    sys.exit()

# lecture des données
try:
    data=open(DATA,"r")
except:
    print "Impossible d'ouvrir en lecture le fichier des donnees [DATA]"
    sys.exit()

# ouverture fichier des résultats
try:
    resultats=open(RESULTATS,"w")
except:  
    print "Impossible de creer le fichier des résultats [RESULTATS]"
    sys.exit()

# on exploite la ligne courante du fichier des données
ligne=data.readline()
while(ligne != ''):
    # on enlève l'éventuelle marque de fin de ligne
    ligne=cutNewLineChar(ligne)
    # on récupère les 3 champs marié:enfants:salaire qui forment la ligne
    (marie,enfants,salaire)=ligne.split(",")
    enfants=int(enfants)
    salaire=int(salaire)
    # on calcule l'impôt
    impot=calculImpots(marie,enfants,salaire,limites,coeffR,coeffN)
    # on inscrit le résultat
    resultats.write("{0}:{1}:{2}:{3}\n".format(marie,enfants,salaire,impot))
    # on lit une nouvelle ligne
    ligne=data.readline()
# on ferme les fichiers
data.close()
resultats.close()

Résultats

Les mêmes que précédemment.

Programme (impots_02b)

La méthode getTables ci-dessus (lignes 6-36) rend un tuple (erreur, limites, coeffR, coeffN) où erreur est un message d'erreur éventuellement vide. On peut vouloir gérer ces cas d'erreurs avec des exceptions. Dans ce cas :

  • en cas d'erreur, la méthode getTables lance une exception ;
  • sinon elle rend le tuple (limites, coeffR, coeffN).

Le code de la méthode getTables devient alors le suivant :

getTables
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
def getTables(IMPOTS):
    # IMPOTS : le nom du fichier contenant les données des tables limites, coeffR, coeffN
    # le fichier IMPOTS existe-t-il ? Si non alors l'exception IOError est lancée dans ce cas
    data=open(IMPOTS,"r")
  
    # création des 3 listes - on suppose que les lignes sont syntaxiquement correctes
    # -- ligne 1
    ligne=data.readline()
    if ligne== '':
        raise RuntimeError ("La  ligne du fichier {0} est absente".format(IMPOTS))
    limites=cutNewLineChar(ligne).split(":")
    for i in range(len(limites)):
        limites[i]=int(limites[i])
    # -- ligne 2
    ligne=data.readline()
    if ligne== '':
        raise RuntimeError ("La  ligne du fichier {0} est absente".format(IMPOTS))
    coeffR=cutNewLineChar(ligne).split(":")
    for i in range(len(coeffR)):
        coeffR[i]=float(coeffR[i])
    # -- ligne 3
    ligne=data.readline()
    if ligne== '':
        raise RuntimeError ("La  ligne du fichier {0} est absente".format(IMPOTS))
    coeffN=cutNewLineChar(ligne).split(":")
    for i in range(len(coeffN)):
        coeffN[i]=float(coeffN[i])
    # fin
    return (limites,coeffR,coeffN)
  • ligne 4 : on ne teste pas si l'ouverture du fichier échoue. Si elle échoue, une exception IOError est lancée. On laisse celle-ci remonter au programme appelant ;
  • lignes 9-10 : on lance une exception pour indiquer que la première ligne attendue est absente. On utilise une exception prédéfinie RuntimeError. On peut également créer ses propres classes d'exception. Nous le ferons un peu plus loin ;
  • lignes 16-17 et 23-24 : on refait la même chose pour les lignes 2 et 3.

Le code du programme principal devient alors le suivant :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
# ------------------------------------------------ main
# définition des constantes
DATA="data.txt"
RESULTATS="resultats.txt"
IMPOTS="impots.txt"

# les données nécessaires au calcul de l'impôt ont été placées dans le fichier IMPOTS
# à raison d'une ligne par tableau sous la forme
# val1:val2:val3...

erreur=False
try:
    (limites,coeffR,coeffN)=getTables(IMPOTS)
except IOError, message:
    erreur=True
except RuntimeError, message:
    erreur=True

# y a-t-il eu une erreur ?
if(erreur):
    print "L'erreur suivante s'est produite : {0}\n".format(message)
    sys.exit()

# lecture des données
...
  • lignes 12-17 : on appelle la méthode getTables et on gère les deux exceptions qu'elle peut lancer : IOError et RuntimeError. Dans cette gestion, on se contente de noter qu'il y a eu erreur ;
  • lignes 20-22 : on affiche le message d'erreur de l'exception interceptée et on arrête le programme.

précédentsommairesuivant

  

Licence Creative Commons
Le contenu de cet article est rédigé par Serge Tahé et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2013 Developpez.com.