Tradutor de código morse Python

Aug 18 2020

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

6 RichardNeumann Aug 18 2020 at 19:25

Estilo Geral

Sua tradução dictusa 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. CamelCaseestá reservado para classes: outputMessageoutput_message, def Encrypt(...)def encrypt(...), etc.

atuação

Usar a Get_Keyfunçã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 Encryptfunçã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 Encryptfunçã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}cryptcom {en,de}code.

Globais

Usar variáveis ​​globais como outputMessagepode ter efeitos colaterais desagradáveis ​​quando o programa é usado como uma biblioteca. Todo o código abaixo da def Play_Soundfunção deve ir para uma def main()função que você pode invocar via

if __name__ == '__main__':
    main()

Na parte inferior da unidade.