Traduttore di codice Morse Python
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
Stile generale
La tua traduzione dict
utilizza 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: outputMessage
→ output_message
, def Encrypt(...)
→ def encrypt(...)
, ecc.
Prestazione
L'utilizzo della Get_Key
funzione 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 Encrypt
funzione 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 Encrypt
funzione 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}crypt
con {en,de}code
.
Globali
L'uso di variabili globali come outputMessage
può avere effetti collaterali negativi quando il programma viene utilizzato come libreria. Tutto il codice sotto la def Play_Sound
funzione dovrebbe andare in una def main()
funzione che puoi invocare tramite
if __name__ == '__main__':
main()
Nella parte inferiore dell'unità.