Overall, nice first post. Your code is clear, and follows pep8 quite well. WRT to you OOP style, I would make some changes. Firstly, encrypt
and decrypt
really shouldn't be private methods, as they will only be called from outside the class. I also probably would not store the message and key in a class instance, but rather have your methods be encrypt(self, message, key)
and have decrypt do the same.
In terms of the cleanliness of your code, your encrypt and decrypt methods would be cleaner if you used itertools.cycle
to keep track of the key. All these changes yield the following methods. Also, instead of subtracting 90, and adding 64, it would probably be easier to just subtract 25
def encrypt(self, message, key):
encrypted = ""
for letter, key_i in zip(message, itertools.cycle(key)):
if ord(letter) + key_i > 90:
encrypted += chr(ord(letter) + key_i - 25)
else:
encrypted += (chr(ord(letter) + key_i)
return encrypted
def decrypt(self, message, key):
decrypted = ""
for letter, key_i in zip(message, itertools.cycle(key)):
if ord(letter) - key_i < 65:
new_key = 65 - (ord(letter) - key_i)
new_letter = chr(91 - new_key)
decrypted += new_letter
else:
decrypted += chr(ord(letter) - key_i)
return decrypted
One sign that these are good changes is that they simplify your driving code to
if __name__ == "__main__":
flag = True
while flag:
userChoice = encrypt_or_decrypt()
message = get_message()
key = get_key()
if userChoice in ("e", "E"):
encrypted = Vigenere.encrypt(message, key)
print(encrypted)
else:
decrypted = Vigenere.decrypt(message, key)
print(decrypted)
userInput = input("\nAgain? (Y/N): ")
while userInput not in ("y", "Y", "n", "N"):
userInput = input("\nAgain? (Y/N): ")
if userInput in ("y", "Y"):
continue
elif userInput in ("n", "N"):
print("Exiting.")
flag = False
input("\n\nPress the enter key to exit.")