While loop not taking 'if' statement into account
Question:
I’m trying to write a program in Python where the user is asked to input a number of hours after which a countdown starts in seconds, however I want to also make sure that no floats/strings are inputted and if they are, the user needs to be prompted with the same question and input a correct value. If an integer is inputted then I want the program to jump to the next statement (hence ‘pass’ on line 4). However, whatever I type in, the program always jumps to the next statement, regardless of whether it’s a string or a float.
TimeHours = input("Countdown time in hours:")
while isinstance(TimeHours, int) is True:
pass
if float(TimeHours) / 1 != int(float(TimeHours)):
input('Please input a whole number, decimals are not accepted.')
elif isinstance(TimeHours, str):
input('Alphabetical letters or unknown characters are not allowed, e.g. A, B, C, (, *')
continue
I tried using if statements and defining functions, but I can’t seem to make it work.
Answers:
float(TimeHours) / 1
returns float
. Did you mean float(TimeHours) // 1
. And isinstance(TimeHours, str)
can not be True
as it is checked only if isinstance(TimeHours, int) is True
. So it doesn’t ignore the if
and elif
, it just never enters them.
Side note:
isinstance(TimeHours, int) is True
is redundant, just use isinstance(TimeHours, int)
instead.
like this
while True:
TimeHours = input("Countdown time in hours:")
try:
TimeHours = int(TimeHours)
break
except ValueError as e:
print('Alphabetical letters or unknown characters are not allowed, e.g. A, B, C, (, *')
continue
I think you can:
- get user input
- check if it’s numeric (since the input is always a string you can use this method)
- print a message if it’s not and start the loop over
- cast to integer and break from the loop if it is
while True:
time_hours = input("Countdown time in hours:")
if time_hours.isnumeric() is False:
print("Please input a whole number. Decimals, alphabetical letters or unknown characters are not allowed.")
continue
time_hours = int(time_hours)
break
Side notes:
- python likes sneak_case
- dividing even using
//
does NOT always yield an integer (see for yourself e.g. print(type(2//3.))
in REPL)
- python has strong (and dynamic, but that doesn’t matter here) typing , so you have to be explicit about type casting
Write a function that returns an integer value and which handles any problems with the user input. Something like this:
def get_time():
while True:
try:
return int(input('Countdown time in hours: '))
except ValueError:
print('Whole numbers only please')
Personally I would use a function instead of a while loop. Mostly because I use tkinter in everything I do so while loops are out of the question.
You can build a function to handle the check like this:
def get_time_in_hours_from_user(message=None):
global time_hours
if message is not None:
print(message)
th = input("Countdown time in hours:")
if th.isdigit():
time_hours = th
print(f'The value provided is a valid integer: {th}')
# Provide the rest of your executable code here or reference another function to execute code.
else:
print(f'The value provided is not a valid integer: {th}')
get_time_in_hours_from_user()
get_time_in_hours_from_user()
Results:
Countdown time in hours:2.2
The value provided is not a valid integer: 2.2
Countdown time in hours:abc
The value provided is not a valid integer: abc
Countdown time in hours:5
The value provided is a valid integer: 5
Process finished with exit code 0
Alternatively if you want the user to provide a value in a GUI you can do something like this:
import tkinter as tk
root = tk.Tk()
tk.Label(root, text='Countdown time in hours:').grid(row=0, column=0)
entry = tk.Entry(root)
entry.grid(row=0, column=1)
def get_time_in_hours_from_user(message=None):
global time_hours
if message is not None:
print(message)
th = entry.get().strip()
if th.isdigit():
time_hours = th
lbl['text'] = f'The value provided is a valid integer: {th}'
# Provide the rest of your executable code here or reference another function to execute code.
else:
lbl['text'] = f'The value provided is not a valid integer: {th}'
tk.Button(root, text='Submit', command=get_time_in_hours_from_user).grid(row=1, column=0, columnspan=2, sticky='ew')
lbl = tk.Label(root)
lbl.grid(row=2, column=0, columnspan=2, sticky='ew')
root.mainloop()
Results:
I’m trying to write a program in Python where the user is asked to input a number of hours after which a countdown starts in seconds, however I want to also make sure that no floats/strings are inputted and if they are, the user needs to be prompted with the same question and input a correct value. If an integer is inputted then I want the program to jump to the next statement (hence ‘pass’ on line 4). However, whatever I type in, the program always jumps to the next statement, regardless of whether it’s a string or a float.
TimeHours = input("Countdown time in hours:")
while isinstance(TimeHours, int) is True:
pass
if float(TimeHours) / 1 != int(float(TimeHours)):
input('Please input a whole number, decimals are not accepted.')
elif isinstance(TimeHours, str):
input('Alphabetical letters or unknown characters are not allowed, e.g. A, B, C, (, *')
continue
I tried using if statements and defining functions, but I can’t seem to make it work.
float(TimeHours) / 1
returns float
. Did you mean float(TimeHours) // 1
. And isinstance(TimeHours, str)
can not be True
as it is checked only if isinstance(TimeHours, int) is True
. So it doesn’t ignore the if
and elif
, it just never enters them.
Side note:
isinstance(TimeHours, int) is True
is redundant, just use isinstance(TimeHours, int)
instead.
like this
while True:
TimeHours = input("Countdown time in hours:")
try:
TimeHours = int(TimeHours)
break
except ValueError as e:
print('Alphabetical letters or unknown characters are not allowed, e.g. A, B, C, (, *')
continue
I think you can:
- get user input
- check if it’s numeric (since the input is always a string you can use this method)
- print a message if it’s not and start the loop over
- cast to integer and break from the loop if it is
while True:
time_hours = input("Countdown time in hours:")
if time_hours.isnumeric() is False:
print("Please input a whole number. Decimals, alphabetical letters or unknown characters are not allowed.")
continue
time_hours = int(time_hours)
break
Side notes:
- python likes sneak_case
- dividing even using
//
does NOT always yield an integer (see for yourself e.g.print(type(2//3.))
in REPL) - python has strong (and dynamic, but that doesn’t matter here) typing , so you have to be explicit about type casting
Write a function that returns an integer value and which handles any problems with the user input. Something like this:
def get_time():
while True:
try:
return int(input('Countdown time in hours: '))
except ValueError:
print('Whole numbers only please')
Personally I would use a function instead of a while loop. Mostly because I use tkinter in everything I do so while loops are out of the question.
You can build a function to handle the check like this:
def get_time_in_hours_from_user(message=None):
global time_hours
if message is not None:
print(message)
th = input("Countdown time in hours:")
if th.isdigit():
time_hours = th
print(f'The value provided is a valid integer: {th}')
# Provide the rest of your executable code here or reference another function to execute code.
else:
print(f'The value provided is not a valid integer: {th}')
get_time_in_hours_from_user()
get_time_in_hours_from_user()
Results:
Countdown time in hours:2.2
The value provided is not a valid integer: 2.2
Countdown time in hours:abc
The value provided is not a valid integer: abc
Countdown time in hours:5
The value provided is a valid integer: 5
Process finished with exit code 0
Alternatively if you want the user to provide a value in a GUI you can do something like this:
import tkinter as tk
root = tk.Tk()
tk.Label(root, text='Countdown time in hours:').grid(row=0, column=0)
entry = tk.Entry(root)
entry.grid(row=0, column=1)
def get_time_in_hours_from_user(message=None):
global time_hours
if message is not None:
print(message)
th = entry.get().strip()
if th.isdigit():
time_hours = th
lbl['text'] = f'The value provided is a valid integer: {th}'
# Provide the rest of your executable code here or reference another function to execute code.
else:
lbl['text'] = f'The value provided is not a valid integer: {th}'
tk.Button(root, text='Submit', command=get_time_in_hours_from_user).grid(row=1, column=0, columnspan=2, sticky='ew')
lbl = tk.Label(root)
lbl.grid(row=2, column=0, columnspan=2, sticky='ew')
root.mainloop()
Results: