Function name
rot13
is a specific name given to a general function. According to Wikipedia ROT13 is:
a simple letter substitution cipher that replaces a letter with the
letter 13 letters after it in the alphabet. ROT13 is a special case of
the Caesar cipher, developed in ancient Rome.
So this name denotes that the function rotates a string only by 13, which it doesn't. So you can give it a more general name like rotated_word
.
Documentation
You've documented your funtion the wrong way using comments instead of a docstring (read it, it's another useful link). Docstrings are better than comments in documenting functions, as you can view a function's docstring using the built-in function help
, to know how to use the function.
Remove # If the final number is greater than 122..
it's not needed. You suppose that whoever reads your code knows Python, so you don't need to explain everything to them.
Return value
Your function prints the result instead of returning it, which gets the job done but makes the function less reusable. Suppose that you want to read a textfile (using Python), encrypt it using Caesar cipher, and then write the ciphertext to a new textfile. Or that you have a list of strings and want to make a new list with these strings encrypted. What will you do? Sure you can make other functions to get this done, but if you make this function return the rotated text you can reuse it in these two cases (and more).
Getting the key
I suggest a function take the key and that will make sure that the input is valid and return it as its return value.
A function to rotate letters
I suggest making a function called rotated_letter
which will rotate a letter and then return this rotated letter and we will use it in rotated_word
. This will make the code more readable and reusable.
Key
I don't know why yoy don't accept 1 as a key. I am not an expert about cryptography, but I think it can be accepted. So I suggest you accept numbers between 1 and 25.
Decoding
You mentioned that your code codes a text or decodes it. It does the first part but doesn't do the second. I therefore suggest making a function to get the mode.
Calling other functions
I suggest making a function called main
and using if __name__ == "__main__"
, as was suggested, to call it. In main
we would call other functions and put all global variables.
Here is your code after refactoring:
def rotated_letter(letter, key):
"""Rotates a given letter by a given number.
letter: str
key: int
Returns: str
"""
if letter.isalpha():
num = ord(letter)
if (num + key) > 122:
x = (num + key) - 122
return chr(x + ord('a') - 1)
else:
return chr(num + key)
else:
return letter
def rotated_word(word, key):
"""Rotates a word by a given key.
word: str
key: int
Returns: str
"""
new_word = ""
for letter in word:
new_letter = rotated_letter(letter, key)
new_word += new_letter
return new_word
def get_key():
"""Asks for an integer between 1 and 25.
Returns: int
"""
while True:
try:
key = int(input('Input the key you want to use from 1 to 25:\n'))
if key in range(1, 26):
return key
except:
print("\nPlease enter an integer.\n")
def get_mode():
"""Asks for a mode (coding or decoding).
Returns: str
"""
while True:
mode = input('Enter C to code or D to decode:\n').upper()
if mode in ('C', 'D'):
return mode
def main():
word = input('Input the text you want to code:\n').lower()
key = get_key()
mode = get_mode()
if mode == 'C':
print(rotated_word(word, key))
else:
print(rotated_word(word, -key))
if __name__ == "__main__":
main()
Notes
I depended on some points from ChatterOne's answer, and edited somethings according to it.
reinvent-the-wheel
otherwise you'll get responses telling you that it's already been done. \$\endgroup\$