Monoalphabetic Substitution Cipher

In light of this months Community Challenge, I've taken a stab at building something related. Keep in mind, this isn't a submission for the challenge, just a utility to help in the later process of completing the challenge.

What we have here is your simple encryption and decryption (with a given key) tool. I'd like to know if what I have is the most efficient, the most well written, and the simplest form of these functions.

import random

alpha = "abcdefghijklmnopqrstuvwxyz"

def encrypt(original, key=None):

if key is None:
l = list(alpha)
random.shuffle(l)
key = "".join(l)

new = []

for letter in original:
new.append(key[alpha.index(letter)])

return ["".join(new), key]

def decrypt(cipher, key=None):
if key is not None:
new = []
for letter in cipher:
new.append(alpha[key.index(letter)])

return "".join(new)
# we'll have an else here for the actual Community Challenge!


I'm nowhere near an expert with Python, so if I'm not following coding standards, please guide me there too.

A simple test might be:

e = encrypt("helloworld", None)
print(e)
print(decrypt(e[0], e[1]))


and we'd get something along the lines of:

['wussndnkst', 'qxvtupaweroslynzhkbigcdjmf']
helloworld


"abcdefghijklmnopqrstuvwxyz" is just the constant string.ascii_lowercase.

Whenever you have this pattern:

some_list = []
for dummy in some_iterable:
some_list.append(some_function_of(dummy))


… that's a candidate for replacement with a list comprehension.

alpha.index(letter) and its inverse could be a performance issue when processing longer messages. Making a dictionary for the translation table would be better. Note that any character that is not ASCII lowercase will cause a ValueError. For encrypt(),

translation = dict(zip(key, string.ascii_lowercase))
ciphertext = ''.join(translation.get(c, c) for c in original)


Here, translation.get(c, c) causes unrecognized characters to be passed through. You can use translation[c] to restore the original exception-raising behaviour.

• Oh excellent! I've managed to learn a bit more and fix everything you suggested. However, I don't think I understand how I could make "a dictionary for the translation table", could you elaborate please? – Alex L Jun 5 '15 at 20:15
• Added code in Rev 2. – 200_success Jun 5 '15 at 20:31