Traductor de código Morse de Python
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
Estilo general
Su traducción dict
utiliza 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
. CamelCase
está reservado para las clases: outputMessage
→ output_message
, def Encrypt(...)
→ def encrypt(...)
, etc.
Actuación
El uso de la Get_Key
funció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 Encrypt
funció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
Encrypt
Actualmente, 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}crypt
con {en,de}code
.
Globals
El uso de variables globales como outputMessage
puede tener efectos secundarios desagradables cuando el programa se usa como biblioteca. Todo el código debajo de la def Play_Sound
funció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.