This page contains a number of questions and exercises to give you a chance to practise what you have learned this session. You should create a new .py Python file for each exercise.
We’ve now covered all the topics on this course so to finish off, work through this final exercise. It is designed to give you a chance to pratise what you’ve learned on some new code.
Make a new directory alongside the bestpractices folder called crypto. In the Terminal change to that directory with cd ../crypto and in the Python Console change there with %cd ../crypto. In that directory make two new files called morse.py and test_morse.py:
# A lookup dictionary which, given a letter will return the morse code equivalent_letter_to_morse = {'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':'--..','0':'-----', '1':'.----', '2':'..---', '3':'...--', '4':'....-','5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',' ':'/'}# This will create a dictionary that can go from the morse back to the letter_morse_to_letter = {}for letter in _letter_to_morse: morse = _letter_to_morse[letter] _morse_to_letter[morse] = letterdef encode(message): morse = []for letter in message: letter = letter.lower() morse.append(_letter_to_morse[letter])# We need to join together Morse code letters with spaces morse_message =" ".join(morse)return morse_messagedef decode(message): english = []# Now we cannot read by letter. We know that morse letters are# separated by a space, so we split the morse string by spaces morse_letters = message.split(" ")for letter in morse_letters: english.append(_morse_to_letter[letter])# Rejoin, but now we don't need to add any spaces english_message ="".join(english)return english_message
Overwriting morse.py
from morse import encode, decodedef test_encode():assert encode("SOS") =="... --- ..."
This module is designed to convert message to and from Morse code. It provides one function which takes an English message and converts it to a Morse code string, separated by spaces and another function which takes the Morse code string and converts it to English.
Exercise
Add documentation to the morse module and to the encode and decode functions. Make sure you detail the inputs, outputs and give an example of their usage. Look at the tests to get an idea of how it works or try importing morse in the Python Console and have a play with the functions to understand them.
Answer
# A lookup dictionary which, given a letter will return the morse code equivalent_letter_to_morse = {'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':'--..','0':'-----', '1':'.----', '2':'..---', '3':'...--', '4':'....-','5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',' ':'/'}# This will create a dictionary that can go from the morse back to the letter_morse_to_letter = {}for letter in _letter_to_morse: morse = _letter_to_morse[letter] _morse_to_letter[morse] = letterdef encode(message):""" Encode a message from English to Morse Code Args: message (str): the English message to encode Returns: str: The encoded message Examples: >>> encode("Help us") ".... . .-.. .--. / ..- ..." """ morse = []for letter in message: letter = letter.lower() morse.append(_letter_to_morse[letter])# We need to join together Morse code letters with spaces morse_message =" ".join(morse)return morse_messagedef decode(message):""" Decode a message from Morse Code to English Args: message (str): the Morse Code message to decode Returns: str: The decoded English message Examples: >>> encode(".... . .-.. .--. / ..- ...") "help us" """ english = []# Now we cannot read by letter. We know that morse letters are# separated by a space, so we split the morse string by spaces morse_letters = message.split(" ")for letter in morse_letters: english.append(_morse_to_letter[letter])# Rejoin, but now we don't need to add any spaces english_message ="".join(english)return english_message
Writing morse.py
Exercise
Add a test for the decode function to test_morse.py and check it passes with pytest
Parametrise both tests to give several examples. Make sure you include upper and lower case letters as well as checking what happens if you pass in empty strings
Make sure to use --doctest-modules to run the documentation examples that you added in the last exercise
Hint: When writing doctests, it cares whether your test output uses single or double quotes (' or "). Use single quotes for doctest outputs.
Answer
# A lookup dictionary which, given a letter will return the morse code equivalent_letter_to_morse = {'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':'--..','0':'-----', '1':'.----', '2':'..---', '3':'...--', '4':'....-','5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',' ':'/'}# This will create a dictionary that can go from the morse back to the letter_morse_to_letter = {}for letter in _letter_to_morse: morse = _letter_to_morse[letter] _morse_to_letter[morse] = letterdef encode(message):""" Encode a message from English to Morse Code Args: message (str): the English message to encode Returns: str: The encoded message Examples: >>> encode("Help us") '.... . .-.. .--. / ..- ...' """ morse = []for letter in message: letter = letter.lower() morse.append(_letter_to_morse[letter])# We need to join together Morse code letters with spaces morse_message =" ".join(morse)return morse_messagedef decode(message):""" Decode a message from Morse Code to English Args: message (str): the Morse Code message to decode Returns: str: The decoded English message Examples: >>> decode(".... . .-.. .--. / ..- ...") 'help us' """ english = []# Now we cannot read by letter. We know that morse letters are# separated by a space, so we split the morse string by spaces morse_letters = message.split(" ")for letter in morse_letters: english.append(_morse_to_letter[letter])# Rejoin, but now we don't need to add any spaces english_message ="".join(english)return english_message
What happens if you pass in the string "Don't forget to save us" to encode?
Hint: The problem is caused by the ' in the string
Edit morse.py to raise a ValueError in this situation instead.
Write a test to make sure that the ValueError is raised when a string with a ' is passed in.
Parametrise that test with some other examples including the & and £ characters.
Answer
# A lookup dictionary which, given a letter will return the morse code equivalent_letter_to_morse = {'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':'--..','0':'-----', '1':'.----', '2':'..---', '3':'...--', '4':'....-','5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.',' ':'/'}# This will create a dictionary that can go from the morse back to the letter_morse_to_letter = {}for letter in _letter_to_morse: morse = _letter_to_morse[letter] _morse_to_letter[morse] = letterdef encode(message):""" Encode a message from English to Morse Code Args: message (str): the English message to encode Returns: str: The encoded message Examples: >>> encode("Help us") '.... . .-.. .--. / ..- ...' """ morse = []for letter in message: letter = letter.lower()if letter notin _letter_to_morse:raiseValueError(f"Cannot encode \"{message}\". Character \"{letter}\" not in Morse dictionary") morse.append(_letter_to_morse[letter])# We need to join together Morse code letters with spaces morse_message =" ".join(morse)return morse_messagedef decode(message):""" Decode a message from Morse Code to English Args: message (str): the Morse Code message to decode Returns: str: The decoded English message Examples: >>> decode(".... . .-.. .--. / ..- ...") 'help us' """ english = []# Now we cannot read by letter. We know that morse letters are# separated by a space, so we split the morse string by spaces morse_letters = message.split(" ")for letter in morse_letters: english.append(_morse_to_letter[letter])# Rejoin, but now we don't need to add any spaces english_message ="".join(english)return english_message