Python Forum
User input only takes the last number
Thread Rating:
  • 2 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
User input only takes the last number
#1
Basically. You have 7 iterations you must enter for pints of blood, or blood donations. Then, it calculates the total, average, and the high and low amount of blood donations. This type of thing could possibly be useful for when you are doing blood donations. The only thing is, the pints_collected is only taking into account the last digit the user inputs. I feel I am missing something simple but I just can't find it.

Any help is appreciated and I attached my code below.


def pints_collected():
    counter = 0
    pints = 0
    while counter < 7:
        counter = counter + 1
        pints = int(input("Enter pints collected: "))

    return pints


def calculate_total(pints):
    '''The getTotal(pints, pintsTotal) function:'''
    pints_total = 0


    pints_total = pints


    return pints_total


def calculate_average(pints_total):
    pints_avg = pints_total / 7
    return pints_avg



def dispInfo(pints_total, pints_avg):
    print("The total number of pints donated was: ", pints_total)
    print("The average # of pints donated was %.2f " % pints_avg)  # display float with 2 decimal

    return pints_total, pints_avg


def main():
    pints = pints_collected()
    pints_total = calculate_total(pints)
    pints_avg = calculate_average(pints_total)
    pints_total, pints_avg = dispInfo(pints_total, pints_avg)

main()
Reply
#2
    while counter < 7:
        counter = counter + 1
        pints = int(input("Enter pints collected: "))
The code above will loop 8 times (including 0)
each time you get the input pints, and then overwrite the previous value ofpints, before it is used for anything.
It's also very confusing (not illegal) that you use the same name 'pints' as two separate variables (because of scope)
if two different functions.
Reply
#3
Ok, I think I understand what you mean by the overwriting and I will try using an array.

Could you elaborate more on me using the variable pints as two separate variables?

Thank you!
Reply
#4
you want to collect seven pints of blood (not from the same donor, I hope)

so you need to accumulate the number,
so change your loop to accumulate the input value:
pints += int(input("Enter pints collected: "))
(you should check to make sure not zero, and isdigit(), but that wasn't part of your assignment))

the counter serves no purpose, so get rid of it.
The 7 iterations is taken care of by the loop.

when the loop finished, divide pints by 7
and return that value,
this can be done in one step.
return total_pints/7
so now you don't need the calculate function
Reply
#5
Ok so I redid my code(with the help of my teacher) and now I am running into the problem with validating the user input. Everything works great if they input a float number. yet if they input a string or space I get this error. I have a feeling that my code is stepping on each other somewhere but I can't find it. I don't want to convert the string, just error out nicely. Under the error is my updated code.
Traceback (most recent call last):
  File "C:/Users/Eman/Desktop/lab5.py", line 101, in <module>
    main()
  File "C:/Users/Eman/Desktop/lab5.py", line 93, in main
    pints_collected_during_drive = get_pints_for_drive()
  File "C:/Users/Eman/Desktop/lab5.py", line 50, in get_pints_for_drive
    pints_collected[counter] = get_pints_for_hour()
  File "C:/Users/Eman/Desktop/lab5.py", line 38, in get_pints_for_hour
    user_input = float(get_real("Enter pints collected: "))
ValueError: could not convert string to float: 
HOURS = 7


def valid_float_number(value):
    try:
        float(value)
        return True
    except ValueError:
        return False


def valid_value(value, prompt):
    while not valid_float_number(value):
        print("Please try again.")
        value = input(prompt)
        return value
    if float(value) < 0 or value == "":
        return False
    else:
        return True




def get_real(prompt):
    value = ""

    value = input(prompt)
    while not valid_value(value, prompt):
        print(value, "is less than 0")
        value = input(prompt)
    return value


def get_pints_for_hour():
    user_input = float(get_real("Enter pints collected: "))
    if user_input == "":
        print("nope")

    return user_input



def get_pints_for_drive():
    pints_collected = [0.0 for x in range (HOURS)]
    counter = 0
    while counter < HOURS:
        pints_collected[counter] = get_pints_for_hour()
        counter += 1
    return pints_collected


def calculate_average_pints(pints_collected_during_drive):
    total_pints = 0
    counter = 0

    while counter < HOURS:
        total_pints += pints_collected_during_drive[counter]
        counter += 1
    return float(total_pints / HOURS)


def display_results(average_pints, minimum, maximum):
    print("The average number of pints donated is ", "{:.2f}".format(average_pints))
    print("The highest pints donated is ", maximum)
    print("The lowest pints donated is ", minimum)


def is_yes_or_no(value):
    return value == "yes" or value == "no"


def yes_or_no(prompt):
    value = ""
    value = input(prompt)
    while not is_yes_or_no(value):
        value = input(prompt)
    if value == "yes":
        return True
    else:
        return False

def prompt_done():
    prompt = "Do you want to end program? (Enter no or yes): "
    return yes_or_no(prompt)


def main():
    done = False
    while not done:
        pints_collected_during_drive = get_pints_for_drive()
        average_pints = calculate_average_pints(pints_collected_during_drive)
        minimum_pints = min(pints_collected_during_drive)
        maximum_pints = max(pints_collected_during_drive)
        display_results(average_pints, minimum_pints, maximum_pints)
        done = prompt_done()


main()
Reply
#6
(Nov-21-2017, 02:49 AM)Austin11 Wrote: Ok so I redid my code(with the help of my teacher) and now I am running into the problem with validating the user input. Everything works great if they input a float number. yet if they input a string or space I get this error. I have a feeling that my code is stepping on each other somewhere but I can't find it. I don't want to convert the string, just error out nicely. Under the error is my updated code.

Hello there! What you are looking for is the ValueError exception. I believe a good way to implement this would be as follows:
def a_function(): # A Function
    try:
        while:
            # Code is being executed
    except ValueError: # Except when code raises a ValueError
        print("That's not a number!") # Optional
        return a_function() # Then return a_function()
Think about where in your code this may be implemented best!

For more information on Errors and Exceptions, refer to the following python documentation:
https://docs.python.org/3/tutorial/errors.html

Regards,
Prrz
Reply
#7
(Nov-21-2017, 03:28 AM)Prrz Wrote:
(Nov-21-2017, 02:49 AM)Austin11 Wrote: Ok so I redid my code(with the help of my teacher) and now I am running into the problem with validating the user input. Everything works great if they input a float number. yet if they input a string or space I get this error. I have a feeling that my code is stepping on each other somewhere but I can't find it. I don't want to convert the string, just error out nicely. Under the error is my updated code.

Hello there! What you are looking for is the ValueError exception. I believe a good way to implement this would be as follows:
def a_function(): # A Function
    try:
        while:
            # Code is being executed
    except ValueError: # Except when code raises a ValueError
        print("That's not a number!") # Optional
        return a_function() # Then return a_function()
Think about where in your code this may be implemented best!

For more information on Errors and Exceptions, refer to the following python documentation:
https://docs.python.org/3/tutorial/errors.html

Regards,
Prrz

Ok, quick question on this. Are you saying I should add a new function in order to satisfy the ValueError or clean up one of my validating functions? Just trying to clarify things so I understand better.
Thanks!
Reply
#8
(Nov-21-2017, 04:09 AM)Austin11 Wrote:
(Nov-21-2017, 03:28 AM)Prrz Wrote: Hello there! What you are looking for is the ValueError exception. I believe a good way to implement this would be as follows:
def a_function(): # A Function
    try:
        while not done:
            # Code is being executed
    except ValueError: # Except when code raises a ValueError
        print("That's not a number!") # Optional
        return a_function() # Then return a_function()
Think about where in your code this may be implemented best!

For more information on Errors and Exceptions, refer to the following python documentation:
https://docs.python.org/3/tutorial/errors.html

Regards,
Prrz

Ok, quick question on this. Are you saying I should add a new function in order to satisfy the ValueError or clean up one of my validating functions? Just trying to clarify things so I understand better.
Thanks!

I'm suggesting cleaning up an existing function that is already written. I tried to format the example I made to mimic one that already exists in your code, perhaps I should have been more clear.

I did not want to simply solve it for you, but if you do get stuck I will gladly help. I added a small snippet from the example I posted in this post, that should also add clarity to my suggestion.

ps. I know you raised a ValueError exception at the beginning of your code, you had the right idea,
but think about how this may not work as intended. Hopefully, that clears up some confusion.

For the sake of not re-writing your code, this is all you need in this function.

def valid_float_number(value):
        float(value)
        return True
Reply
#9
I made enhancements to my code and I have it validating every input correctly. My only thing now is that I when they input a string the code closes out nicely. That is great but is there a way to call the "value" function so it can loop until the user inputs a valid number?

Also, I am with you 100%, I don't want to be given the answers just guided in the right direction, I will never learn from that. It just sucks because the book doesn't show any examples of what are assignments actually are.

Here is my updated code:
HOURS = 7


def valid_float_number(value):
    float(value)
    return True


def valid_value(value, prompt):
    while not valid_float_number(value):
        value = input(prompt)
        return value

    if float(value) < 0 or value == "":
        print(value, "is less than 0!")
        return False
    else:
        return True


def get_real(prompt):
    value = ""

    value = input(prompt)
    while not valid_value(value, prompt):

        value = input(prompt)

    return value


def get_pints_for_hour():
    user_input = float(get_real("Enter pints collected: "))


    return user_input


def get_pints_for_drive():
    pints_collected = [0.0 for x in range(HOURS)]
    counter = 0
    while counter < HOURS:
        pints_collected[counter] = get_pints_for_hour()
        counter += 1
    return pints_collected


def calculate_average_pints(pints_collected_during_drive):
    total_pints = 0
    counter = 0

    while counter < HOURS:
        total_pints += pints_collected_during_drive[counter]
        counter += 1
    return float(total_pints / HOURS)


def display_results(average_pints, minimum, maximum):
    print("The average number of pints donated is ", "{:.2f}".format(average_pints))
    print("The highest pints donated is ", maximum)
    print("The lowest pints donated is ", minimum)


def is_yes_or_no(value):
    return value == "yes" or value == "no"


def yes_or_no(prompt):
    value = ""
    value = input(prompt)
    while not is_yes_or_no(value):
        value = input(prompt)
    if value == "yes":
        return True
    else:
        return False


def prompt_done():
    prompt = "Do you want to end program? (Enter no or yes): "
    return yes_or_no(prompt)


def main():
    done = False
    try:
        while not done:
            pints_collected_during_drive = get_pints_for_drive()
            average_pints = calculate_average_pints(pints_collected_during_drive)
            minimum_pints = min(pints_collected_during_drive)
            maximum_pints = max(pints_collected_during_drive)
            display_results(average_pints, minimum_pints, maximum_pints)
            done = prompt_done()
    except ValueError:
        print("Please try again.")
        return main


main()
Reply
#10
(Nov-21-2017, 05:11 PM)Austin11 Wrote: I made enhancements to my code and I have it validating every input correctly. My only thing now is that I when they input a string the code closes out nicely. That is great but is there a way to call the "value" function so it can loop until the user inputs a valid number?

Also, I am with you 100%, I don't want to be given the answers just guided in the right direction, I will never learn from that. It just sucks because the book doesn't show any examples of what are assignments actually are.

Here is my updated code:
HOURS = 7


def valid_float_number(value):
    float(value)
    return True


def valid_value(value, prompt):
    while not valid_float_number(value):
        value = input(prompt)
        return value

    if float(value) < 0 or value == "":
        print(value, "is less than 0!")
        return False
    else:
        return True


def get_real(prompt):
    value = ""

    value = input(prompt)
    while not valid_value(value, prompt):

        value = input(prompt)

    return value


def get_pints_for_hour():
    user_input = float(get_real("Enter pints collected: "))


    return user_input


def get_pints_for_drive():
    pints_collected = [0.0 for x in range(HOURS)]
    counter = 0
    while counter < HOURS:
        pints_collected[counter] = get_pints_for_hour()
        counter += 1
    return pints_collected


def calculate_average_pints(pints_collected_during_drive):
    total_pints = 0
    counter = 0

    while counter < HOURS:
        total_pints += pints_collected_during_drive[counter]
        counter += 1
    return float(total_pints / HOURS)


def display_results(average_pints, minimum, maximum):
    print("The average number of pints donated is ", "{:.2f}".format(average_pints))
    print("The highest pints donated is ", maximum)
    print("The lowest pints donated is ", minimum)


def is_yes_or_no(value):
    return value == "yes" or value == "no"


def yes_or_no(prompt):
    value = ""
    value = input(prompt)
    while not is_yes_or_no(value):
        value = input(prompt)
    if value == "yes":
        return True
    else:
        return False


def prompt_done():
    prompt = "Do you want to end program? (Enter no or yes): "
    return yes_or_no(prompt)


def main():
    done = False
    try:
        while not done:
            pints_collected_during_drive = get_pints_for_drive()
            average_pints = calculate_average_pints(pints_collected_during_drive)
            minimum_pints = min(pints_collected_during_drive)
            maximum_pints = max(pints_collected_during_drive)
            display_results(average_pints, minimum_pints, maximum_pints)
            done = prompt_done()
    except ValueError:
        print("Please try again.")
        return main


main()

Hello again, I see what you mean. Your code currently will reset itself upon receiving a ValueError, making your prior inputs invalid. To fix this I'd highly suggest completely re-organizing your script. Start from scratch, and think of a simpler way to do this (for sake of example, I rewrote this using 31 lines and only 1 function). I appreciate complexity, however, in coding, it's often the simpler solutions that make the most sense. I do have a hard time understanding your code because it does jump around quite a bit, making it hard to follow what goes where and what does what.

Here's my suggestion, start by defining one function, in my case I named mine
def get_pints()
which requires no arguments. In this function, I defined 4 separate variables, one to hold the total number of pints collected (for ease of calculating sum). Next, I defined a blank list (to keep track of every input given, appending it to a list so each number has its own place). Then I defined a counter, much like you did, to easily keep track of how many inputs have been given. Lastly, I defined a boolean, like you did, to register whether to continue the script or not.

To start you off, here is what the beginning of the function looks like:
def get_pints():
    pints_collected = 0
    pints_data = []
    counter = 0
    done = False
    while counter <= 6 and done == False:
            try:
                # Python Stuff
            except ValueError:
                print("That is not a valid entry, try again please.")
                pass
    else:
        # Do some calculations once we've entered all 7 inputs
        # After calculations, ask if user wants to try again, if they do, reset the variables!
With the counter only being able to count up to six, this means everytime I enter a number into the script I make the counter raise by 1, leaving seven places for input, just like your original script (0,1,2,3,4,5,6). After calculations, when asking the user if they wish to exit the program, if answered "yes" you can assign done = True, leaving the while statement unable to execute. If answered "No" you can assign the variables back to their original values, and return to the initial function.

Under the try statement, you would accept the user's input, and you would want to convert it to an integer on the same line. After this, add the input given by the user to the (my_input += pints_collected) "pints_collected" variable, so we can easily define a total number. An important step, is you also want to append the user's input to the blank list "pints_data", this will give each input a unique spot on the list.

Using this method the calculations will be quite simple, and just like the ones you've already used.
   else:
        average = round(pints_collected / 7) # round the number, take the average.
        maximum = max(pints_data) # What's the highest value in our list?
        minimum = min(pints_data) # What's the lowest value in our list?
       # Print your values
        retry = input("Retry? (Yes or No").upper() 
# Ask if user wants to go again, upper() makes their input in uppercase. 
# So when definining your if statement, make sure you use capitlals. 
# (if the_input == "YES)
If you have any questions, feel free to ask!

Regards,
Prrz
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Question Simulate an answer based on user input [Beginner needs guidance] Bombardini 1 1,257 Nov-12-2022, 03:47 AM
Last Post: deanhystad
  Checking the number of input Chrilo06 3 1,973 Mar-14-2022, 07:31 PM
Last Post: deanhystad
  Print user input into triangle djtjhokie 1 2,343 Nov-07-2020, 07:01 PM
Last Post: buran
  Changing Directory based on user input paulmerton4pope 13 7,885 Aug-14-2020, 11:48 AM
Last Post: GOTO10
  Creating a link that takes the user to a random page card51shor 9 6,043 Jul-06-2020, 05:38 AM
Last Post: card51shor
  how to add the user input from file into list wilson20 8 4,229 May-03-2020, 10:52 PM
Last Post: Larz60+
  Writing a function that changes its answer based on user input SirRavenclaw 2 2,759 Dec-21-2019, 09:46 PM
Last Post: Clunk_Head
  Print the longest str from user input edwdas 5 4,051 Nov-04-2019, 02:02 PM
Last Post: perfringo
  how to add user input to a dictionary to a graph KINGLEBRON 3 2,981 Jul-31-2019, 09:09 PM
Last Post: SheeppOSU
  New to Python - tiny coding assistance on user input function and assign to variable Mountain_Duck 1 2,465 Mar-23-2019, 06:54 PM
Last Post: Yoriz

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020