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.

Asked By: Noria

||

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.

Answered By: Yevhen Kuzmovych

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
Answered By: Lian Xucan

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
Answered By: Gameplay

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')
Answered By: Fred

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:

enter image description here

enter image description here

enter image description here

enter image description here

Answered By: Mike – SMT
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.