Problem
Could someone suggest ways to simplify this code, or any other tips? All help is much appreciated. Moreover, should I comment code above or below the line of code (I have to comment as this is a requirement)?
#This imports the time and random modules
import time, random
#This defines a function called comment
def comment():
#This makes the variable startage a global variable rather than a local variable
global startage
#This checks if choice is equal to 1 or equal to 2
if choice == 1 or choice == 2:
if startage < 25:
print("You're a young cat or dog")
elif startage > 25 and startage < 50:
print("You're a middle aged cat or dog")
elif startage > 50:
print("You're an old cat or dog")
elif choice == 3 or choice == 4:
if newage < 25:
print("You're a young cat or dog")
elif newage > 25 and startage < 50:
print("You're a middle aged cat or dog")
elif newage > 50:
print("You're an old cat or dog")
else:
pass
print("Welcome to the animal age calculator")
while True:
time.sleep(1)
choice = int(input("Which age would you like to convert?(Enter the corresponding number)n1. Human ---> Dogn2. Human ---> Catn3. Dog ---> Humann4. Cat ---> Humann5. Generate a random human agen"))
time.sleep(1)
if choice >= 1 and choice <= 4:
startage = int(input("What age would you like to start with?n"))
if choice == 1:
print("You have chosen Human ---> Dog and the Human age is", startage)
if startage < 3:
newage = startage*11
else:
newage = 22+(startage-2)*4
elif choice == 2:
print("You have chosen Human ---> Cat and the Human age is", startage)
if startage == 1:
newage = 15
else:
newage = 25+(startage-2)*4
elif choice == 3:
print("You have chosen Dog ---> Human and the Dog age is", startage)
if startage < 33:
newage = startage/11
else:
newage = (((startage-22)/4)+2)
elif choice == 4:
print("You have chosen Cat ---> Human and the Cat age is", startage)
if startage == 15:
newage = 1
else:
newage = (((startage-22)/4)+2)
elif choice == 5:
print("You have chosen to generate a random human age.")
time.sleep(1)
randomage = random.randint(1,122)
print(randomage)
time.sleep(1)
if choice >= 1 and choice <= 4:
print("Your new age is:", newage)
time.sleep(1)
comment()
restart = (input("Would you like to restart?(Yes or No)")).lower()
while True:
if restart == "yes":
pass
elif restart=="no":
break
Solution
My two most important remarks concern comments and global variables.
Python is a language that is designed to be easily readable. Your three comments simply restate the obvious, and are therefore obnoxious or harmful. (Redundancy simply doubles the burden of code maintenance, as you have to ensure that your comments are consistent with the code.)
The most important kind of documentation in Python is the docstring — and you didn’t write any!
The use of global variables makes it difficult to understand and maintain your code. The presence of a global variable means that a reassignment could have effects beyond the scope of a function. That defeats one of the principal advantages of packaging code into functions, which is to make it clear what the inputs and outputs are for a particular chunk of code.
Simple rewrite
Your “restart” feature doesn’t actually work. I’ve removed it in the code below, and am leaving it as an exercise to you to fix it.
import time, random
def comment(human_equiv_age):
"""
Print a remark based on the human-equivalent age.
"""
if human_equiv_age < 25:
print("You're a young cat or dog")
elif human_equiv_age < 50:
print("You're a middle aged cat or dog")
else:
print("You're an old cat or dog")
def main():
"""
Ask the user for inputs to an animal age conversion, and print
the result.
"""
print("Welcome to the animal age calculator")
time.sleep(1)
choice = int(input(
"Which age would you like to convert? (Enter the corresponding number)n"
"1. Human ---> Dogn"
"2. Human ---> Catn"
"3. Dog ---> Humann"
"4. Cat ---> Humann"
"5. Generate a random human agen"
))
time.sleep(1)
if choice == 5:
print("You have chosen to generate a random human age.")
time.sleep(1)
print(random.randint(1,122))
time.sleep(1)
elif 1 <= choice <= 4:
input_age = int(input("What age would you like to start with?n"))
if choice == 1:
print("You have chosen Human ---> Dog and the Human age is", input_age)
chrono_age = input_age
human_equiv_age = 11 * chrono_age if chrono_age < 3 else 22 + (chrono_age - 2) * 4
output_age = human_equiv_age
if choice == 2:
print("You have chosen Human ---> Cat and the Human age is", input_age)
chrono_age = input_age
human_equiv_age = 15 if chrono_age == 1 else 25 + (chrono_age - 2) * 4
output_age = human_equiv_age
if choice == 3:
print("You have chosen Dog ---> Human and the Dog age is", input_age)
human_equiv_age = input_age
chrono_age = human_equiv_age / 11 if human_equiv_age < 33 else (human_equiv_age - 22) / 4 + 2
output_age = chrono_age
if choice == 4:
print("You have chosen Cat ---> Human and the Cat age is", input_age)
human_equiv_age = input_age
chrono_age = 1 if human_equiv_age == 15 else (human_equiv_age - 22) / 4 + 2
output_age = chrono_age
time.sleep(1)
print("Your new age is:", output_age)
time.sleep(1)
comment(human_equivalent_age)
main()
Some additional remarks:
-
Python supports double-ended inequalities, like
1 <= choice <= 4
. Note that I haven’t used that feature in thecomment()
function, though. Can you see the bug in your code, and why I didn’t use double-ended inequalities there? -
Make the distinction between calendar years and human-equivalent years clear. Those two quantities don’t really have the same units, and that made your
comment()
function messy. -
Your formulae for choices 3 and 4 are the same. Surely, the Cat→Human calculation is not the inverse of the Human→Cat calculation.
There are other changes I would make, but I’ll leave it at this to keep the review simple.
You may consider using python docstring instead of this comment: “#This defines a function called comment”. Something like this:
def comment():
"""Makes a comment about user's age"""
In python you can write
25 < startage < 50
instead of
startage > 25 and startage < 50
And line global startage
is unnecessary, since you don’t have to declare variable as global if you only read it’s value. On the other hand if you assign the value, you have to write “global var_name” to prevent python from creating local variable with the same name.
And you don’t need the inner “while True:” loop: it will start the program from beginning if you answer “no” and hang the program otherwise. Instead of
while True:
if restart == "yes":
pass
elif restart=="no":
break
you need to write just
if restart == "no":
break
Moreover, should I comment code above or below the line of code (I have to comment as this is a requirement)?
In most programming languages comments will appear before the statement, or at least side by side. Putting comments after the statement commented is rare and confusing.
As I’ve learned from the other answers (I’m certainly no python expert), it seems to be usual for python to rather use the docstring format, which applies after the documented statement.
In general write meaningful comments, just repeating the obvious like here
#This defines a function called comment
def comment():
or
#This checks if choice is equal to 1 or equal to 2
if choice == 1 or choice == 2:
isn’t useful. Rather describe what that function actually does (the naming isn’t really intuitive anyways), or why that check needs to be done.
Also regarding the simplification of your code, the comment()
function could be rewritten as
def comment():
#This makes the variable startage a global variable rather than a local variable
global startage
if choice == 1 or choice == 2 or choice == 3 or choice == 4:
if startage < 25:
print("You're a young cat or dog")
elif startage > 25 and startage < 50:
print("You're a middle aged cat or dog")
elif startage > 50:
print("You're an old cat or dog")
else:
pass
without changing the current logic.