6
\$\begingroup\$

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 ---> Dog\n2. Human ---> Cat\n3. Dog ---> Human\n4. Cat ---> Human\n5. Generate a random human age\n"))
    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
\$\endgroup\$
1
  • \$\begingroup\$ Try not to use global variables as much as possible as they make the variable(s) hard to track. A good programmer should return the outcome of the function. \$\endgroup\$ – Akil Riaz May 4 '17 at 13:26
5
\$\begingroup\$

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 ---> Dog\n"
        "2. Human ---> Cat\n"
        "3. Dog ---> Human\n"
        "4. Cat ---> Human\n"
        "5. Generate a random human age\n"
    ))
    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 the comment() 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.

\$\endgroup\$
1
  • \$\begingroup\$ if restart == "no": break \$\endgroup\$ – Anonymous Coder May 4 '17 at 17:38
3
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ The one 'sort-of' exception in python to comments coming before is the docstring which comes after the function definition. While not strictly a comment it serves a similar purpose. \$\endgroup\$ – AChampion May 4 '17 at 4:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.