How to update a global variable based on number of user inputs? - python

I am trying to make a list of weights that are being brought to a trip to outer space. The way I have tried to show how many people are coming is this:
def flcr():
try:
Value1 = int(input())
except ValueError:
print("That was an incorrect format! Try again.")
flcr()
global x
x = Value1
Then the user has to input the weights one by one. This is what I tried:
def enter():
print("How much is each flight crew member bringing on the trip? Enter one entry at a time, this will be Earth weight.")
amount1()
def amount1():
try:
if x > 0:
equation1 = [float(input())]
x - 1
amount1()
else:
print(listFlcr)
except ValueError:
print("That was an incorrect format! Try again.")
enter()
When I input the weights though, I assume x just resets itself instead of subtracting itself by 1, so my input is infinite. I want to have a code that will allow me to enter the right amount of weights, so if I say there are 2 people coming, I can only input two weights.
If someone could help me out I would greatly appreciate it!

There are a number of issues with your current implementation.
You are using recursion to repeat getting inputs, which means you have a function (flcr, amount1) that calls itself until valid inputs are provided. While this could work for user inputs, it is usually unnecessary. There are better ways to ask for user input until they give a valid response, and as mentioned in the comments, use a loop instead.
The code x-1 does not update x. It actually does nothing because the result is not stored anywhere. If you are using an IDE or a linter, it could warn you that this is a "pointless statement". What you probably wanted was x = x - 1.
You are using globals to track how many weights need to be input and how many were input so far. While this could also work, it is again unnecessary. It would be simpler to just pass the number of flight crew members as a function argument.
Here's a solution that replaces the recursive calls with while loops and gets the number of people from one function, then passes the result of that to another function for getting the weights:
def get_num_people():
while True:
try:
return int(input("How many people are coming? "))
except ValueError:
print("That was an incorrect format! Try again.")
def get_weights(num_weights):
print("How much is each flight crew member bringing on the trip?")
all_weights = []
while len(all_weights) < num_weights:
try:
all_weights.append(int(input()))
except ValueError:
print("That was an incorrect format! Try again.")
print(all_weights)
return all_weights
num_people = get_num_people()
get_weights(num_people)
Here's the sample output:
$ python test.py
How many people are coming? 2
How much is each flight crew member bringing on the trip?
12
33
[12, 33]
$ python test.py
How many people are coming? 3
How much is each flight crew member bringing on the trip?
abc
That was an incorrect format! Try again.
89
def
That was an incorrect format! Try again.
100
4
[89, 100, 4]
I know that your question was about how to update the global variable based on user inputs, ... but I think you have a global x because you were using recursive calls. A cleaner solution would be to get rid of both recursion and the global variable.

You don't need global before the comparison of x in that function.
Generally for me, I find it easier to refer to things I want global as globals()[‘x’]. That way I know nothing weird will happen. If globals() refers to global namespace, represented similar to a dictionary, globals()[‘x’] will always point to the global variable x.
If it is intended to be global, declare it globally before everything else. Outside all the functions, x = None, or x = 0, or x = ‘’.

try to replace :
Value1 = int(input())
with :
Value1 = int(str(input("")))

Related

I don't understand why digit not return but "local variable 'total' referenced before assignment" instead [duplicate]

This question already has answers here:
local variable 'servers' referenced before assignment
(3 answers)
Asking the user for input until they give a valid response
(22 answers)
Closed 4 years ago.
I want write a method that asks a user to input a digit, but if the user also inputs a string it needs to ask the user to input again until the correct data is input.
-------code that shows error-------------
def get_total():
try:
total = int(input("How many people you got in total: "))
except:
print("Your data is invalid, please try again.")
get_total()
return total
x = get_total()
print(x)
If you type 5 directly, it will print 5.
However if you type "s" first and then 5, it will throw this error:
"local variable 'total' referenced before assignment"
Can anyone could please tell me why?
If I correct the code like this, it works just fine
------code that works fine-----------------
def get_total():
try:
total = int(input("How many people you got in total: "))
return total
except:
print("Your data is invalid, please try again.")
return get_total()
x = get_total()
print(x)
So why does this happen?
The problem is that when in the code
total = int(input("How many people you got in total: "))
the input is not a number and int throws an exception the local variable total has not been assigned.
In the except part of the first version you are calling get_total recursively but this doesn't set the total variable, just returns you the result (that is ignored).
When (after this successful recursive call) you end up in your return statement the total variable is still unbound and therefore you get an exception.
The key point to understand is that calling get_total recursively is not a "goto". If you want a loop write a loop (e.g. using while), if you want recursion the use recursion.
The reason is that if you enter 5 in first try it assigns total the value of 5 and then returns it
However if you enter the value "s" the except block gets run and it goes back to the function call . Then you enter the value 5 the return statment in the second function call returns 5 and it exits the except block in the first function call.
Then it runs the return statement however the variable total doesnt exist only the value 5 exists
correct code is
def get_total():
try:
total = int(input("How many people you got in total: "))
except:
print("Your data is invalid, please try again.")
total = get_total()
return total
Hope it helps :)
The error code should be modified as:
def get_total():
try:
total = int(input("How many people you got in total: "))
except ValueError:
print("Your data is invalid, please try again.")
total = get_total() # assign return value back to total
return total
You don't receive the returned value from the function when you called within function, so when it encounters return total, Python throws UnboundLocalError.
A better way is to use an infinite loop like following:
def get_total():
while True:
try:
total = int(input("How many people you got in total: "))
return total
except ValueError:
print("Your data is invalid, please try again.")
Note that it's not advised to handle all exceptions once (like except:). Always name the exception with except keyword (ValueError in this case).
I think this code is also correct:
def get_total():
while True: # prompt's the user until a correct input is given(break)
try:
total = int(input("How many people you got in total: "))
break # if the input for total is int, program will break from the loop. if not, program will print an error message and this loop will execute again
except:
print("Your data is invalid, please try again.")
return total
x = get_total()
print(x)
hope it helps

Python user defined list not being recognised within a while true loop

Thanks firstly for bearing with me as a relative newcomer to the world of Python. I'm working on a simple set of code and have been racking my brain to understand where I am going wrong. I suspect it is a relatively simple thing to correct but all searches so far have been fruitless. If this has been covered before then please be gentle, I have looked for a couple of days!
I'm working on the following and after catching and correcting a number of issues I suspect that I'm on the last hurdle:-
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(our_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(our_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(our_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
main()
else:
print("Goodbye")
break`
For some reason the appended (our_list) is not being recognised within the while true loop rendering the statistics calculation void. Any steer would be really appreciated as to where I am missing the obvious, thanks in advance.
Cheers
Bryan
I'm not sure exactly what you mean by "not being recognized", but our_list is a local variable inside main, so it can't be used anywhere but inside main.
So, if you try to use it elsewhere, you should get a NameError.
If your code actually has a global variable with the same name as the local variable that we aren't seeing here, things can be more confusing—you won't get a NameError, you'll get the value of the global variable, which isn't what you want.
The best solution here is to return the value from the function, and then have the caller use the returned value. For example:
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
return our_list
the_list = main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(the_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(the_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(the_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
the_list = main()
else:
print("Goodbye")
break
There are other options—you could pass in an empty list for main to fill, or use a global variable (or, better, a more restricted equivalent like an attribute on a class instance or a closure variable), or refactor your code so everyone who needs to access our_list is inside the same function… but I think this is the cleanest way to do what you're trying to do here.
By the way, this isn't quite the last hurdle—but you're very close:
After any mean, median, or mode, it's going to hit the "Goodbye" and exit instead of going back through the loop. Do you know about elif?
You mixed up '5' and '4' in the menu.
If the user enters 2 and 3 and asks for the mode, your code will dump a ValueError traceback to the screen; probably not what you want. Do you know try/except?
That's all I noticed, and they're all pretty simple things to add, so congrats in advance.
The issue is that our_list was defined in the main() function, and is not visible outside of the main() function scope.
Since you're doing everything in one chunk, you could remove line 1 and 6, taking the code from your main() function and putting it on the same indentation level as the code which follows.
This seems to be because you defined our_list within the main() function. You should probably define it as a global variable by creating it outside the main() function.
You could also put the while loop inside a function and pass in our_list as a parameter to the list.

How to match input with elements in list/dictionary in Python3

I'm very new at coding, and I'm trying to create a shop list with items and prices on it.
That is, once typed in all the items, the function should calculate the sum and stop the moment you exceed the budget.
So I wrote something like:
def shoplist():
list={"apple":30, "orange":20, "milk":60......}
buy=str(input("What do you want to purchase?")
If buy in list:
While sum<=budget:
sum=sum+??
shoplist ()
I really don't know how to match the input of an item with the price in the list...
My first thought is to use 'if', but it's kinda impractical when you have more than 10 items on the list and random inputs.
I'm in desperate need of help....So any suggestions would be nice!! (or if you have a better solution and think me writing it this way is complete garbage... PLEASE let me know what those better solutions are😭😭😭
The code you post will not run in python. list is a builtin and should not be used for a variable name, and is doubly confusing since it refers to a dict object here. input() already returns a str so the cast has no effect. if and while should be lowercase, and there is no indentation, so we have no way of knowing the limits of those statements.
There are so many things wrong, take a look at this:
def shoplist(budget):
prices = {"apple":30, "orange":20, "milk":60}
# Initialise sum
sum = 0
while sum <= budget:
buy = input("What do you want to purchase?")
# Break out of the loop if the user hts <RETURN>
if not buy: break
if buy in prices:
sum += prices[buy] # This gets the price
else:
print("Invalid item", buy)
shoplist(142)
So what have I changed? The budget has to come from somewhere, so I pass it in as a parameter (142, I made that up). I initialise the sum to zero, and I moved the while loop to the outside.
Notice as well lots of whitespace - it makes the code easier to read and has no effect on performance.
Lots of improvements to make. The user should be shown a list of possible items and prices and also how much budget there is left for each purchase. Note as well that it is possible to go over budget since we might only have 30 in the budget but we can still buy milk (which is 60) - we need another check (if statement) in there!
I'll leave the improvements to you. Have fun!
Take a look at this as an example:
# this is a dictionary not a list
# be careful not using python reserved names as variable names
groceries = {
"apple":30,
"orange":20,
"milk":60
}
expenses = 0
budget = 100
cart = []
# while statements, as well as if statements are in lower letter
while expenses < budget:
# input always returns str, no need to cast
user_input = input("What do you want to purchase?")
if user_input not in groceries.keys():
print(f'{user_input} is not available!')
continue
if groceries[user_input] > budget - expenses:
print('You do not have enough budget to buy this')
user_input = input("Are you done shopping?Type 'y' if you are.")
if user_input == 'y':
break
continue
cart.append(user_input)
# this is how you add a number to anotherone
expenses += groceries[user_input]
print("Shopping cart full. You bought {} items and have {} left in your budget.".format(len(cart), budget-expenses))
I've made some changes to your code to make it work, with explanation including using comments indicated by the # symbol.
The two most important things are that all parentheses need to be closed:
fun((x, y) # broken
fun((x, y)) # not broken
and keywords in Python are all lowercase:
if, while, for, not # will work
If, While, For, Not # won't work
You might be confused by True and False, which probably should be lowercase. They've been that way so long that it's too late to change them now.
budget = 100 # You need to initialize variables before using them.
def shoplist():
prices = { # I re-named the price list from list to prices
'apple' : 30, # because list is a reserved keyword. You should only
'orange' : 20, # use the list keyword to initialize list objects.
'milk' : 60, # This type of object is called a dictionary.
} # The dots .... would have caused an error.
# In most programming languages, you need to close all braces ().
# I've renamed buy to item to make it clearer what that variable represents.
item = input('What do you want to purchase? ')
# Also, you don't need to cast the value of input to str;
# it's already a str.
if item in prices:
# If you need an int, you do have to cast from string to int.
count = int(input('How many? '))
cost = count*prices[item] # Access dictionary items using [].
if cost > budget:
print('You can\'t afford that many!')
else:
# You can put data into strings using the % symbol like so:
print('That\'ll be %i.' % cost) # Here %i indicates an int.
else:
print('We don\'t have %s in stock.' % item) # Here %s means str.
shoplist()
A lot of beginners post broken code on StackOverflow without saying that they're getting errors or what those errors are. It's always helpful to post the error messages. Let me know if you have more questions.

Handling input data quality with checks & default value

I am trying to write a code for squaring the user input number in Python. I've created function my1() ...
What I want to do is to make Python to take user input of a number and square it but if user added no value it gives a print statement and by default give the square of a default number for e.g 2
Here is what I've tried so far
def my1(a=4):
if my1() is None:
print('You have not entered anything')
else:
b=a**2
print (b)
my1(input("Enter a Number"))
This is a better solution:
def my1(a=4):
if not a:
return 'You have not entered anything'
else:
try:
return int(a)**2
except ValueError:
return 'Invalid input provided'
my1(input("Enter a Number"))
Explanation
Have your function return values, instead of simply printing. This is good practice.
Use if not a to test if your string is empty. This is a Pythonic idiom.
Convert your input string to numeric data, e.g. via int.
Catch ValueError and return an appropriate message in case the user input is invalid.
You're getting an infinite loop by calling my1() within my1(). I would make the following edits:
def my1(a):
if a is '':
print('You have not entered anything')
else:
b=int(a)**2
print (b)
my1(input("Enter a Number"))
When I read your code, I can see that you are very confused about what you are writing. Try to organize your mind around the tasks you'll need to perform. Here, you want to :
Receive your user inputs.
Compute the data.
Print accordingly.
First, take your input.
user_choice = input("Enter a number :")
Then, compute the data you received.
my1(user_choice)
You want your function, as of now, to print an error message if your type data is not good, else print the squared number.
def my1(user_choice): # Always give meaning to the name of your variables.
if not user_choice:
print 'Error'
else:
print user_choice ** 2
Here, you are basically saying "If my user_choice doesn't exists...". Meaning it equals False (it is a bit more complicated than this, but in short, you need to remember this). An empty string doesn't contain anything for instance. The other choice, else, is if you handled your error case, then your input must be right, so you compute your data accordingly.
In your second line, it should be
if a is None:
I think what you want to do is something like the following:
def m1(user_input=None):
if user_input is None or isinstance(user_input, int):
print("Input error!")
return 4
else:
return int(user_input)**2
print(my1(input("Input a number")))

Transforming an input variable into an interger

I'm completely new to python, and I wanted to create a program that "loads" a number that the user would have entered.
To do this, I made a function with an input variable,
percentage
that I then tried to transform to an interfer,
percentage_int
To then put in a while loop.
However, I get an error message, why?
def loader():
percentage = input("what percentage do you want?")
percentage_int =int(percentage)
x = 0
print("Goal:{} %".format(percentage_int))
while x < percentage_int:
x+=1
print(x)
loader()
You need to do the type conversion, that is in this case from string to integer.
If you dont do so python will consider percentage_int as the input string itself.
percentage = input("what percentage do you want?")
percentage_int = int(percentage)
Go through this tutorial which will help you learn more about type conversions with python.

Categories

Resources