Traducteur de code Morse Python

Aug 18 2020

Je m'enseigne moi-même sur Python ces dernières semaines, je m'intéresse à la cryptographie, aux codes, etc. donc j'ai pensé que démarrer un traducteur de code Morse serait un bon projet. Je sais que mes noms de variables peuvent être différents, il ne s'agit pas vraiment de chiffrer, de déchiffrer, etc. Je cherche surtout des conseils sur la façon dont je peux rendre le code plus propre et où je peux être plus efficace.

Je pense que mon plus gros problème n'est pas vraiment de savoir comment gérer les entrées dans une boucle while comme je le ferais habituellement. Le problème que j'ai eu était que je ne pouvais pas vérifier si l'entrée était «e» ou «d», donc ça devenait vraiment bancal.

Domaines que je sais que je pourrais améliorer:

  • Ajouter une boucle d'entrée
  • Le if, elif, else pour l'action
  • Faire de 'son' une valeur booléenne réelle
  • Trouvez le temps sonore réel pour le dit and dah mais ce n'est pas vraiment un problème de code
# Started: 08/17/2020
# Finished: 08/17/2020
# Takes an input message and outputs the message in morse code
# Keys taken from 'https://en.wikipedia.org/wiki/Morse_code'

from playsound import playsound
import time

# Dictionary that holds each letter and it's corresponding value
dict = {'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': '--..',
        '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----',
        ' ': '/', '.': '.-.-.-', ',': '.-.-', '?': '..--..', "'": '.----.', '!': '-.-.--', '/': '-..-.', '(': '-.--.', ')': '-.--.-',
        ':': '---...', ';': '-.-.-.', '=': '-...-', '+': '.-.-.', '-': '-....-', '_': '..--.-', '"': '.-..-.', '$': '...-..-', '@': '.--.-.'}

outputMessage = ""               # Holds our output message

# Sounds
sound = 'False'
dit = 'dit.wav'
dah = 'dah.wav'


def Encrypt(message):

    output = ''

    for char in message:
        if char in dict:
            output = output + dict[char]
            output = output + ' '

    return output


def Get_Key(val):
    for key, value in dict.items():
        if val == value:
            return key


def Decrypt(message):

    output = ''

    letters = message.split(' ')

    for letter in letters:
        temp = Get_Key(letter)
        output = output + temp

    return output


def Get_Inputs():
    # Get Inputs
    inputString = input('Enter a message to start.\n')
    action = input('(E)ncrypt or (D)ecrypt?\n')

    # Format Inputs
    message = inputString.lower().strip()
    action = action.lower().strip()

    return message, action


def Play_Sound(message):

    for char in message:
        if char == '.':
            playsound(dit)
        elif char == '-':
            playsound(dah)
        elif char == ' ':
            time.sleep(0.15)
        elif char == '/':
            time.sleep(0.30)


message, action = Get_Inputs()

if action == 'e' or action == 'encrypt':
    outputMessage = Encrypt(message)
elif action == 'd' or action == 'decrypt':
    outputMessage = Decrypt(message)
else:
    print('Error!')

print(outputMessage)

print('')
sound = input('Play sound? (T)rue / (F)alse\n')
if sound.lower().strip() == 't' or sound.lower().strip() == 'true':
    Play_Sound(outputMessage)

Réponses

6 RichardNeumann Aug 18 2020 at 19:25

Style général

Votre traduction dictutilise un mot-clé et des lettres minuscules. Envisagez d'écrire des constantes avec des lettres majuscules et de leur donner des noms expressifs comme MORSE_CODES = {...}.

Selon PEP 8 , les fonctions doivent être nommées en utilisant snake_case. CamelCaseest réservé aux classes: outputMessageoutput_message, def Encrypt(...)def encrypt(...), etc.

Performance

L'utilisation de la Get_Keyfonction n'est pas très performante, car elle effectue une recherche linéaire du dict. Inversez simplement le dictionnaire de traduction une fois, puis utilisez-le:

MORSE_ENCODING = {
    'a': '.-',
    'b': '-...',
    ...
}
MORSE_DECODING = {value: key for key, value in MORSE_ENCODING.items()}

...

        temp = MORSE_DECODING[letter]

Gestion des erreurs

Actuellement, la Encryptfonction ignore silencieusement tous les caractères non traduisibles. Envisagez ValueError()plutôt de lancer un pour indiquer qu'une entrée non valide a été fournie:

def encode(message):
    """Encodes a string into morse code."""

    code = ''

    for index, char in enumerate(message):
        try:
            code += MORSE_ENCODING[char.lower()]
        except KeyError:
            raise ValueError(f'Char "{char}" at {index} cannot be encoded.')

        code += ' '

    return code[:-1]  # Remove trailing space.


def decode(morse_code):
    """Decodes morse code."""

    message = ''

    for index, sequence in enumerate(morse_code.split()):
        try:
            message += MORSE_DECODING[sequence]
        except KeyError:
            raise ValueError(f'Cannot decode code "{sequence}" at {index}.')

    return message

Exactitude

Votre Encryptfonction renvoie actuellement toujours un espace de fin. Vous pouvez éviter cela en revenant output[:-1].

Terminologie

La conversion du code morse en texte dans les deux sens n'est pas vraiment un cryptage dans son sens. Vous voudrez peut-être reformuler {en,de}cryptavec {en,de}code.

Globales

L'utilisation de variables globales comme outputMessagepeut avoir des effets secondaires désagréables lorsque le programme est utilisé comme bibliothèque. Tout le code sous la def Play_Soundfonction doit entrer dans une def main()fonction que vous pouvez appeler via

if __name__ == '__main__':
    main()

Au bas de l'appareil.