Traductor de código Morse de Python

Aug 18 2020

Me he estado enseñando Python durante las últimas semanas, tengo interés en criptografía, códigos, etc., así que pensé que comenzar un traductor de código Morse sería un buen proyecto. Sé que los nombres de mis variables pueden ser diferentes, no se trata realmente de encriptar, desencriptar, etc. Lo que más busco es consejos sobre cómo puedo hacer el código más limpio y dónde puedo ser más eficiente.

Creo que mi mayor problema es no saber realmente cómo manejar las entradas en un ciclo while como lo haría normalmente. El problema que tuve fue que no pude verificar si la entrada era 'e' o 'd', por lo que se volvió realmente inestable.

Áreas que sé que podría mejorar:

  • Agregar bucle de entrada
  • El if, elif, else para la acción
  • Hacer 'sonido' un valor booleano real
  • Encuentre el tiempo de sonido real para el dit y dah, pero eso no es realmente un problema de código
# 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)

Respuestas

6 RichardNeumann Aug 18 2020 at 19:25

Estilo general

Su traducción dictutiliza una palabra clave y letras minúsculas. Considere escribir constantes con letras mayúsculas y darles nombres expresivos como MORSE_CODES = {...}.

De acuerdo con PEP 8 , las funciones deben nombrarse usando snake_case. CamelCaseestá reservado para las clases: outputMessageoutput_message, def Encrypt(...)def encrypt(...), etc.

Actuación

El uso de la Get_Keyfunción no es muy eficaz, ya que realiza una búsqueda lineal del dict. Simplemente invierta el diccionario de traducción una vez y luego úselo:

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

...

        temp = MORSE_DECODING[letter]

Manejo de errores

Actualmente, la Encryptfunción omite silenciosamente todos los caracteres no traducibles. Considere lanzar un ValueError()en su lugar para indicar que se proporcionó una entrada no válida:

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

Exactitud

EncryptActualmente, su función siempre devuelve un espacio final. Puedes evitar eso volviendo output[:-1].

Terminología

La conversión de código morse a texto de ida y vuelta no es realmente un cifrado en su sentido. Es posible que desee reformular {en,de}cryptcon {en,de}code.

Globals

El uso de variables globales como outputMessagepuede tener efectos secundarios desagradables cuando el programa se usa como biblioteca. Todo el código debajo de la def Play_Soundfunción debe ir a una def main()función que pueda invocar a través de

if __name__ == '__main__':
    main()

En la parte inferior de la unidad.