Traduttore di codice Morse Python

Aug 18 2020

Ho insegnato a me stesso Python nelle ultime settimane, sono interessato alla crittografia, ai codici, ecc. Quindi ho pensato che avviare un traduttore di codice Morse sarebbe stato un buon progetto. So che i nomi delle mie variabili potrebbero essere diversi, non si tratta di crittografia, decrittografia, ecc. Per lo più cerco consigli su come rendere il codice più pulito e dove posso essere più efficiente.

Penso che il mio problema più grande non sia davvero sapere come gestire gli input in un ciclo while come farei di solito. Il problema che ho avuto è stato che non potevo controllare se l'ingresso era "e" o "d", quindi è diventato davvero instabile.

Aree che so di poter migliorare:

  • Aggiungi loop di input
  • If, elif, else per l'azione
  • Rendi "sound" un valore booleano effettivo
  • Trova il tempo del suono effettivo per dit e dah, ma non è davvero un problema di codice
# 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)

Risposte

6 RichardNeumann Aug 18 2020 at 19:25

Stile generale

La tua traduzione dictutilizza una parola chiave e lettere minuscole. Considera l'idea di scrivere costanti con lettere maiuscole e di assegnare loro nomi espressivi come MORSE_CODES = {...}.

Secondo PEP 8 , le funzioni dovrebbero essere denominate usando snake_case. CamelCaseè riservato alle classi: outputMessageoutput_message, def Encrypt(...)def encrypt(...), ecc.

Prestazione

L'utilizzo della Get_Keyfunzione non è molto performante, poiché esegue una ricerca lineare del dict. Basta invertire una volta il detto di traduzione e poi usarlo:

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

...

        temp = MORSE_DECODING[letter]

Gestione degli errori

Attualmente la Encryptfunzione ignora silenziosamente tutti i caratteri non traducibili. Considera di lanciare un ValueError()invece per indicare che è stato fornito un input non valido:

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

Correttezza

La tua Encryptfunzione attualmente restituisce sempre uno spazio finale. Puoi evitarlo tornando output[:-1].

Terminologia

La conversione da codice morse a testo avanti e indietro non è davvero una crittografia nel suo senso. Potresti voler riformulare {en,de}cryptcon {en,de}code.

Globali

L'uso di variabili globali come outputMessagepuò avere effetti collaterali negativi quando il programma viene utilizzato come libreria. Tutto il codice sotto la def Play_Soundfunzione dovrebbe andare in una def main()funzione che puoi invocare tramite

if __name__ == '__main__':
    main()

Nella parte inferiore dell'unità.