Tradutor de código morse Python
Tenho ensinado Python sozinho nas últimas semanas, tenho interesse em criptografia, códigos, etc., então achei que começar um tradutor de código Morse seria um bom projeto. Eu sei que meus nomes de variáveis podem ser diferentes, não é realmente criptografar, descriptografar, etc. Estou principalmente procurando conselhos sobre como posso tornar o código mais limpo e onde posso ser mais eficiente.
Acho que meu maior problema é não saber como lidar com as entradas em um loop while como eu normalmente faria. O problema que eu tinha é que não conseguia verificar se a entrada era 'e' ou 'd', então ficou muito confuso.
Áreas que sei que poderia melhorar:
- Adicionar loop de entrada
- O if, elif, else para a ação
- Faça 'soar' um valor booleano real
- Encontre o tempo real de som para dit e dah, mas isso não é realmente um 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)
Respostas
Estilo Geral
Sua tradução dict
usa uma palavra-chave e letras minúsculas. Considere escrever constantes com letras maiúsculas e dar-lhes nomes expressivos como MORSE_CODES = {...}
.
De acordo com o PEP 8 , as funções devem ser nomeadas usando snake_case
. CamelCase
está reservado para classes: outputMessage
→ output_message
, def Encrypt(...)
→ def encrypt(...)
, etc.
atuação
Usar a Get_Key
função não tem muito desempenho, uma vez que executa uma pesquisa linear do dicionário. Basta reverter o dicionário de tradução uma vez e usá-lo:
MORSE_ENCODING = {
'a': '.-',
'b': '-...',
...
}
MORSE_DECODING = {value: key for key, value in MORSE_ENCODING.items()}
...
temp = MORSE_DECODING[letter]
Tratamento de erros
Atualmente, a Encrypt
função ignora silenciosamente todos os caracteres não traduzíveis. Considere lançar um ValueError()
para indicar que uma entrada inválida foi fornecida:
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
Exatidão
Sua Encrypt
função atualmente sempre retorna um espaço à direita. Você pode evitar isso voltando output[:-1]
.
Terminologia
A conversão de código morse em texto para frente e para trás não é realmente uma criptografia em seu sentido. Você pode querer reformular {en,de}crypt
com {en,de}code
.
Globais
Usar variáveis globais como outputMessage
pode ter efeitos colaterais desagradáveis quando o programa é usado como uma biblioteca. Todo o código abaixo da def Play_Sound
função deve ir para uma def main()
função que você pode invocar via
if __name__ == '__main__':
main()
Na parte inferior da unidade.