Comment ne pas répéter des portions de code ? [Résolu]

Signaler
-
Messages postés
2
Date d'inscription
mardi 23 mars 2021
Statut
Membre
Dernière intervention
24 mars 2021
-
Bonjour,
Je suis débutant en python et j'aimerais avoir une relecture critique de mon petit script. J'ai trois problèmes : je déclare des variables globales mais je ne sais pas si dans mon script c'est nécessaire où si je peux faire d'une autre manière. Je répète du code dans ma fonction decode() mais là aussi je ne sais pas comment simplifier la tache, je n'est même pas le début d'une idée. Et enfin ma gestion des arguments optionnels de la ligne de commande dans main() me paraissent pas pro. Je mets le code complet à la fin de mon poste. Je vous remercie du temps que vous me consacrerez. Et j'ai vraiment envie d'apprendre de vos remarques et explications.
Bien cordialement,

Louis-Fiacre

# -*- coding: utf-8 -*-
from collections import Counter
import sys, getopt

global ordered_french_dico
french_dico = dict() # issu de https://www.apprendre-en-ligne.net/crypto/stat/francais.html
french_dico = {'a': 8.15, 'b': 0.97, 'c': 3.15, 'd': 3.73, 'e': 17.39, 'f': 1.12, 'g': 0.97, 'h': 0.85, 'i': 7.31, 'j': 0.45, 'k': 0.02, 'l': 5.69, 'm': 2.87, 'n': 7.12, 'o': 5.28, 'p': 2.80, 'q': 1.21, 'r': 6.64, 's': 8.14, 't': 7.22, 'u': 6.38, 'v': 1.64, 'w': 0.03, 'x': 0.41, 'y': 0.28, 'z': 0.15,}
ordered_french_dico = sorted(french_dico.items(), key=lambda x: x[1], reverse = True) #valeurs décroissantes
global ordered_english_dico
english_dico = dict() # issu de https://www.apprendre-en-ligne.net/crypto/stat/anglais.html
english_dico = {'a': 8.08, 'b': 1.67, 'c': 3.18, 'd': 3.99, 'e': 12.56, 'f': 2.17, 'g': 1.80, 'h': 5.27, 'i': 7.24, 'j': 0.14, 'k': 0.63, 'l': 4.04, 'm': 2.60, 'n': 7.38, 'o': 7.47, 'p': 1.91, 'q': 0.09, 'r': 6.42, 's': 6.59, 't': 9.15, 'u': 2.79, 'v': 1.00, 'w': 1.89, 'x': 0.21, 'y': 1.65, 'z': 0.07,}
ordered_english_dico = sorted(english_dico.items(), key=lambda x: x[1], reverse = True) #valeurs décroissantes
global ordered_italian_dico
italian_dico = dict() # issu de https://fr.sttmedia.com/frequences-de-lettres-italien
italian_dico = {'a': 11.00, 'b': 1.05, 'c': 4.30, 'd': 3.39, 'e': 11.97, 'f': 1.01, 'g': 1.65, 'h': 1.43, 'i': 10.27, 'j': 0.00, 'k': 0.00, 'l': 5.70, 'm': 2.87, 'n': 7.02, 'o': 10.08, 'p': 2.96, 'q': 0.45, 'r': 6.19, 's': 5.48, 't': 6.97, 'u': 3.28, 'v': 1.75, 'w': 0.00, 'x': 0.00, 'y': 0.00, 'z': 0.85,}
ordered_italian_dico = sorted(italian_dico.items(), key=lambda x: x[1], reverse = True) #valeurs décroissantes
global freq
freq = dict()
global alpha
alpha = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']

def sorti(src_in, decal): #fonction de substitution des caractères
list_decal = []
for car in src_in:
upper = False
if car not in alpha:
if car.isupper() == False:
car_decal = car

if car.isupper() == True:
car = car.lower()
upper = True
if car in alpha:
ide = (alpha.index(car) + decal)
while ide >= len(alpha):
ide = ide - len(alpha)
car_decal = alpha[ide]
if upper == True:
car_decal = car_decal.upper()

list_decal.append(car_decal)
text_decal = "".join(list_decal)

print("[!] Texte sorti : \n",text_decal)
return text_decal

def taux(a, b): #donne taux de différence entre frequence des caractères de la source et d'un dictionnaire de référence
somme_score = 0
score = []
for i in range(0,len(a)):
taux = (a[i][1] - b[i][1])
if taux < 0:
taux = taux * (-1)
score.append(taux)
somme_score = sum(score)/len(score)
return somme_score

def pretraitement(text_0):
text = text_0.lower()
text = text.replace(",", "")
text = text.replace("'", "")
text = text.replace(" ", "")
text = text.replace("\n", "")
return text

def read(src_in): #extrait la source et renvoie une chaine de caractère
try:
source = open(src_in, "r")
text_0 = "".join(source.readlines())# passe d'une list à une chaine de caracrère
print("[!] Texte source :\n",text_0)
finally:
source.close()
return text_0

def write(src_out, text_decal): # ecrit le text de sorti dans un nouveau fichier
try:
source = open(src_out, "a")
source.write(text_decal)
print("[!] Texte de sorti dans: ", src_out)
finally:
source.close
return True

def code(src_in, decal, src_out = ""):
decal = int(decal)
text_0 = read(src_in)
print("[!] Substitution par ",decal," lettres")
text_out = sorti(text_0, decal)
if src_out != "":
write(src_out, text_out)

def decode(src_in, src_out = ""):
text_0 = read(src_in)
text = pretraitement(text_0)
length_text = len(text) #longueur du texte
occur = Counter(text) # occurence de chaque caractère
for (key, value) in occur.items():
pourcent = round((value / length_text)*100, 2)
freq[key] = pourcent # frequence de pourcentage des occurences
alpha_freq = sorted(freq.items(), key=lambda x: x[0]) #alphabétique
value_freq = sorted(freq.items(), key=lambda x: x[1], reverse = True) #valeurs décroissantes
FR = taux(value_freq, ordered_french_dico)
ANG = taux(value_freq, ordered_english_dico)
IT = taux(value_freq, ordered_italian_dico)

if FR < ANG and FR < IT:
print("[!] Texte source de ",length_text,"caractères en français")
decal = alpha.index(ordered_french_dico[0][0]) - alpha.index(value_freq[0][0])
print("[!] Lettre ",value_freq[0][0],"=",ordered_french_dico[0][0],"Substitution par ",decal," lettres")

elif ANG < FR and ANG < IT:
print("[!] Texte source de ",length_text,"caractères en anglais")
decal = alpha.index(ordered_english_dico[0][0]) - alpha.index(value_freq[0][0])
print("[!] Lettre ",value_freq[0][0],"=",ordered_english_dico[0][0],"Substitution par ",decal," lettres")

elif IT < FR and IT < ANG:
print("[!] Texte source de ",length_text,"caractères en italien")
decal = alpha.index(ordered_italian_dico[0][0]) - alpha.index(value_freq[0][0])
print("[!] Lettre ",value_freq[0][0],"=",ordered_italian_dico[0][0],"Substitution par ",decal," lettres")
text_out = sorti(text_0, decal)
if src_out != "":
print(text_out)
write(src_out, text_out)

def usage():
print("[!] Script pour coder et decoder un texte par substitution de lettre\n",
" --decode ou -d attend un argument obligatoire [fichier_source.txt] et un argument optionnel [fichier_out.txt]\n",
" --code ou -c attend deux arguments obligatoires [fichier_source.txt] [integer] et un argument optionnel [fichier_out.txt]\n",
" --help ou -h Affiche les commandes possibles")

def main(argv):
try:
opts, args = getopt.getopt(argv, "hdc",["help", "decode","code"])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
print(opt, arg)
if opt in ("-h", "--help"):
print(arg)
usage()
sys.exit()
elif opt in ("-d", "--decode"):
try: src_out = argv[2]
except: src_out = ""
decode(argv[1],src_out)
elif opt in ("-c", "--code"):
try: src_out = argv[3]
except: src_out = ""
code(argv[1], argv[2], src_out)

if __name__ == "__main__":
main(sys.argv[1:])

1 réponse

Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021
823
bonjour,
il est utile de préciser le langage quand tu utilises les balises de code. explications ici: https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

à propos de decode():
1) ne manque t'il pas un else? que doit faire le programme si aucune des trois conditions n'ait satisfaite?
2) comment simplifier et éviter de recopier du code: commence par identifier clairement ce qui change et ce qui ne change pas.
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021
823 >
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021

c'est presque toujours une erreur d'utiliser des noms de variables spécifiques aux données, tel que tu le fais.

pour bien concevoir un programme, le plus important, souvent, est de bien concevoir les structures de données. il est, certainement, important d'y réfléchir avant d'écrire le programme.
>
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021

Je comprends, je vais y réfléchir alors, peut être en cherchant du coté du module collections. Je suis ravi d'avoir poster mon code, je n'aurais jamais envisager les choses comme ça. Le problème de mon code est donc une question de structure de donnée. Alors et à votre avis où devrais-je diriger mes recherches, vers les tuples ?
Messages postés
2
Date d'inscription
mardi 23 mars 2021
Statut
Membre
Dernière intervention
24 mars 2021
>
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021

Voici une solution basée sur un dictionnaire et des listes, merci monsieur pour votre aide
dicos = {"français":{'a': 8.15, 'b': 0.97, 'c': 3.15,ETC...},"anglais":{'a': 8.08, 'b': 1.67, 'c': 3.18,ETC...},"italien":{'a': 11.00, 'b': 1.05, 'c': 4.30,ETC...}, {ETC...}}
ordered_dicos = list()
languages = list()
for name, dic in dicos.items():
    languages.append(name)
    ordered_dicos.append(sorted(dic.items(), key=lambda x: x[1], reverse = True)) #valeurs décroissantes

Et plus loin dans decode()
list_taux = []
    for i in range(0,len(dicos)):
        list_taux.append(taux(value_freq, ordered_dicos[i]))
    for indice, val in enumerate(list_taux):
        if val == min(list_taux):
            top_language = indice
    decal = decalage(ordered_dicos[top_language], languages[top_language], length_text,value_freq)
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021
823 >
Messages postés
2
Date d'inscription
mardi 23 mars 2021
Statut
Membre
Dernière intervention
24 mars 2021

suggestions, dans decode():
list_taux = [ taux(value_freq, ordered_dicos[i]) for i in range(len(dicos)) ]
top_language = list_taux.index(min(list_taux))
Messages postés
2
Date d'inscription
mardi 23 mars 2021
Statut
Membre
Dernière intervention
24 mars 2021
>
Messages postés
14989
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
7 avril 2021

Hyper concis, merci !