4
\$\begingroup\$

While working through a challenge in the beginning of a book I'm reading. I wanted to make my first program more versatile in its responses while trying to fix any exceptions that it was throwing at me. I'm not really sure how well I've made it and I'm looking for any advice on where I can improve it. Here is the program:


def agelist(r1= 1, r2= 250):
        return[item for item in range(r1, r2+1)]
z = agelist()

def agecheck(x):
    agelimit = input("I'm sorry, please enter a valid number for your age.")
    q = int(agelimit)
    if q in z:
        paymentmethod2(q)
    elif q not in z:
        agecheck(q)



def paymentmethod(x):
        print("Here is your receipt. Thanks and have a great day!")

def paymentmethod2(x):
    payment2 = input("Please enter either a 1 for Cash or 2 for Credit.")
    y = int(payment2)
    if y == 1:
        print("Thanks! Have a nice day!")
    elif y == 2:
        print("Thanks! Have a nice day!!")
    else:
        paymentmethod2(y)

def savingspace(x):
    x = int(payment)
    if x == 1:
        paymentmethod(x)
    elif x == 2:
        paymentmethod(x)
    else:
        paymentmethod2(x)

while True:
    try:
        age1 = int(input("I see you'd like to buy some cigarettes. How old are you?"))
    except ValueError:
        print("Sorry, I didn't understand that.")
        continue
    else:
        break
age = int(age1)

if age in z:
        if age < 21:
            if age >= 13:
                print("You're too young to buy these things!")
                print("Go find something else to buy.")
            else:
                print("This isn't a place for you son.")
                print("Come back with your parents next time.")

        elif age < 125:
            if age <= 40:
                print("Sorry for the trouble. Pesky new laws in this county make us have to check.")
                payment= input("How'd you like to pay? Press 1 on the numpad for Cash or 2 for Credit.")
                savingspace(payment)
            else:
                print("Those good ol' cowboys amiright hehe, wouldn't be Texas without em!")
                payment= input("How'd you like to pay? Press 1 on the numpad for Cash or 2 for Credit.")
                savingspace(payment)
        else:
            print("Out of respect for your ancient being; I will forget what I saw here. Take your cigarettes and go.")
         
elif age not in z:
        agecheck(age)
input()

This is how I tried to fix my errors before I read chocolate's post.

z = range(1, 251) #specifies range of integers that this program will use

def agecheck(x): #function allows age to be corrected to a number in z list. My while loops are cause a bit of a mess, but it works kinda.
    while True:
        try:
            agelimit = input("Voided, please enter a valid number for your age again.")
            q = int(agelimit)
            if q in z:
                paymentmethod2(q)
            elif q not in z:
                agecheck(q)
        except ValueError:
            print("Please choose a number below 250.")
            continue
        else:
            break
          


def paymentmethod(x): #funtion which receives param from savingspace function and prints closing str
        print("Here is your receipt. Thanks and have a great day!")

def paymentmethod2(x): #final function is called when an int other than 1 or 2 is passed to savingspace(x)
    payment2 = input("Please enter either a 1 for Cash or 2 for Credit.") #requests input to be either 1 or 2
    y = int(payment2)
    if y == 1:
        print("Thanks! Have a nice day!")
    elif y == 2:
        print("Thanks! Have a nice day!!")
    else:
        paymentmethod2(y) #if input isnt 1 or 2, calls itself with a different variable to fix
#for some reason entering a non integer at this point bounces it back to the while loop where payment is defined??
def savingspace(x): #function I used to save space in program and sort the input provided
    x = int(payment)
    if x == 1:
        paymentmethod(x)
    elif x == 2:
        paymentmethod(x) #if payment is 1 or 2, calls paymentmethod(x) function
    else:
        paymentmethod2(x) #if its any other number, calls paymentmethod2(x) to fix input

while True: #Beginning of program: asks & defines age and loops if input is not an integer
    try:
        age = int(input("I see you'd like to buy some cigarettes. How old are you?"))
    except ValueError:
        print("Sorry, I didn't understand that.")
        continue
    else:
        break

#takes age and sorts it to print str based on user's input
if age in z: #checks if user's age is valid based on number list defined by function z
        if age < 21:
            if age >= 13:
                print("You're too young to buy these things!")
                print("Go find something else to buy.")
            else:
                print("This isn't a place for you son.")
                print("Come back with your parents next time.")

        elif age < 125:
            if age <= 40:
                print("Sorry for the trouble. Pesky new laws in this county make us have to check.")
                while True: #loop handles ValueError exception when a non integer is input
                    try:
                        payment= input("How'd you like to pay? Press 1 on the numpad for Cash or 2 for Credit.")
                        #sets payment pref as variable
                        savingspace(payment)#passes payment pref variable to function which sorts the payment var
                    except ValueError:
                        print("Sorry only 1 or 2 is allowed to be input.")
                        continue
                    else:
                        break
            else:
                print("Those good ol' cowboys amiright hehe, wouldn't be Texas without em!")
                while True: #same as above
                    try:
                        payment= input("How'd you like to pay? Press 1 on the numpad for Cash or 2 for Credit.")
                        savingspace(payment)
                    except ValueError:
                        print("Sorry only 1 or 2 is allowed to be input.")
                        continue
                    else:
                        break
        else:
            print("Out of respect for your ancient being; I will forget what I saw here. Take your cigarettes and go.")
         
elif age not in z: #if the number provided isn't valid in list; calls function agecheck to ensure a valid input
        agecheck(age)
input() #so the program doesnt just shut off after the last response
\$\endgroup\$
3
  • \$\begingroup\$ Provide more context, what does the program do? \$\endgroup\$ Dec 2 '20 at 0:46
  • \$\begingroup\$ Thanks, by that do you mean that I should add comments on which parts do what and how it all flows together? \$\endgroup\$
    – parapuffer
    Dec 2 '20 at 1:14
  • 1
    \$\begingroup\$ Hi parapuffer. You should add the problem your code solves in your post (the context), otherwise it's hard for reviewers to see exactly what you want your code to do \$\endgroup\$
    – IEatBagels
    Dec 2 '20 at 14:18
3
\$\begingroup\$
  1. Instead of using range to define a list of numbers, use the <, > and = operators to save efficiency.

  2. In many of your functions, you've given then an argument that the function doesn't use at all, which only wastes efficiency.

  3. Instead of the redundant

if y == 1:
    print("Thanks! Have a nice day!")
elif y == 2:
    print("Thanks! Have a nice day!")

You can do:

if y in [1, 2]:
    print("Thanks! Have a nice day!")

and same goes for the others.

  1. Instead of defining age1, and then defining another variable, age, to store the exact same value, and never using age1 again, simply use the age1 (which I renamed to age).

  2. You can define a function that will take care of retrieving a valid age from the user.

Here is the implementation:

def get_age():
    while True:
        try:
            age = int(input("How old are you? "))
        except ValueError:
            print("Sorry, I didn't understand that. ")
            continue
        if 250 < age or age < 1:
            print("I'm sorry, please enter a valid number for your age.")
            continue
        return age

def paymentmethod():
    print("Here is your receipt. Thanks and have a great day!")

def paymentmethod2():
    print("Thanks! Have a nice day!!")

def savingspace(x):
    if x == '1':
        paymentmethod()
    else:
        paymentmethod2()

print("I see you'd like to buy some cigarettes.")
age = get_age()
if age < 13:
    print("This isn't a place for you son.")
    print("Come back with your parents next time.")
elif age < 21:
    print("You're too young to buy these things!")
    print("Go find something else to buy.")
elif age < 125:
    if age < 40:
        print("Sorry for the trouble. Pesky new laws in this county make us have to check.")
    else:
        print("Those good ol' cowboys amiright hehe, wouldn't be Texas without em!")
    while True:
        payment = input("How'd you like to pay? Press 1 on the numpad for Cash or 2 for Credit. ")
        if payment in ['1', '2']:
            savingspace(payment)
            break
        print("Please enter a valid number.")
else:
    print("Out of respect for your ancient being; I will forget what I saw here. Take your cigarettes and go.")
input()
```
\$\endgroup\$
8
  • 2
    \$\begingroup\$ I prefer if not 1 <= age <= 250: over if 250 < age or age < 1:. \$\endgroup\$
    – Graipher
    Dec 2 '20 at 5:21
  • \$\begingroup\$ Wow your version makes much more sense than mine and fixes the issues I was having. I didn't realize that I could shorten the while loop you used for payment like that. The fix I tried ended up looping back in on itself whenever a function after it had a wrong input. Thanks a lot \$\endgroup\$
    – parapuffer
    Dec 2 '20 at 5:28
  • \$\begingroup\$ Would y in (1, 2) be even more idiomatic than y in [1, 2]? \$\endgroup\$ Dec 2 '20 at 6:15
  • \$\begingroup\$ x in range(0, 10) isn't much slower than 0 <= x < 10. x in range(0, 20000000000) is still a constant-time operation. So long as this isn't happening in a tight loop, speed shouldn't be a concern. (Clarity might be, though, so I agree with that suggestion – just not the rationale.) Edit: The original answer was building a list, from a range, so you are right; I'm leaving this comment in the hopes it might be useful to others. \$\endgroup\$
    – wizzwizz4
    Dec 2 '20 at 7:34
  • \$\begingroup\$ @wizzwizz4 You're wrong. What I provided is 10 times faster than range. Of course, human may not be able to feel the difference at all, but using the time.perf_counter function show the difference clearly. \$\endgroup\$
    – Chocolate
    Dec 2 '20 at 12:56
0
\$\begingroup\$

I'll add the rest of my comments in when I have time, but here's some stuff:


You can replace...

def agelist(r1= 1, r2= 250):
        return[item for item in range(r1, r2+1)]
z = agelist()

...with:

z = range(1, 251)
\$\endgroup\$
3
  • \$\begingroup\$ Thanks, I'm not too knowledgeable yet on all of the built in functions so I appreciate the help. \$\endgroup\$
    – parapuffer
    Dec 2 '20 at 1:15
  • 1
    \$\begingroup\$ No, it's z = range(1, 251). \$\endgroup\$
    – Chocolate
    Dec 2 '20 at 4:56
  • \$\begingroup\$ @Chocolate -- Whoops, you're right. \$\endgroup\$ Dec 2 '20 at 15:08

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.