1

I am trying to find a neater way to do the following input check:

def intInputCheck():
    while True:
        try:
            INPUT = int(input("INPUT -> "))
            return INPUT
        except ValueError:
            print("Please only input integers")

def createGroup():

    possibleSupervisors = ["USER1","USER2"] #etc

    print("Possible supervisors:\n{}".format(possibleSupervisors))
    for i in range(0, len(possibleSupervisors)):
        print(i, ":", possibleSupervisors[i][0])
    """
    supervisor = intInputCheck
    while supervisor() not in range(0, len(possibleSupervisors)):
        print("Please only input numbers in the range provided")
    """
    #The above kinda works, but i cant then use the variable "supervisor"
    """

    supervisor = intInputCheck()
    while supervisor not in range(0, len(possibleSupervisors)):
        supervisor = intInputCheck()
        print("Please only enter integers in the given range")
    """
    """
       The above works, however I end up giving out two print statements if 
       the user doesnt input an integer which I don't want, I want it to 
       only output the print statement if that specific error occurs, in 
       this, If a str is entered, the func will output "only enter ints" and 
       then the while will output "only ints in given range" which is a pain
    """

I am also trying to see if closures could be useful in simplifying this code, the reason I want to do this is to make my code neater (I think having the same input before and then inside a while loops looks bad). The reason for the function is so that I can use this input checking function in various parts of my program

James Green
  • 125
  • 12

1 Answers1

1

You can "enhance" your validator function - you probably should resort to two different functions because this one does too much for one single function, but here we go:

def intInputCheck(text,error,options=[]):
    """Prints 'text' and optional a list of (1-based) 'options' and loops
    till a valid integer is given. If 'options' are given, the integer must
    be inside 1..len(options).

    The return is either an integer or a tuple of the 1-based list index and the 
    corresponding value from the list."""
    msg = [text]
    test = None
    if options:
        test = range(1,len(options)+1)
        for num,t in enumerate(options,1):
            msg.append("{:>2} : {}".format(num,t))
        msg.append("Choice -> ")

    while True:
        try:
            INPUT = int(input('\n'.join(msg)))
            if test is None:
                return INPUT
            elif INPUT in test:
                return (INPUT,options[INPUT-1])
            else:
                raise ValueError
        except ValueError:
            print(error)

k = intInputCheck("INPUT -> ","Please only input integers")

sup = intInputCheck("Possible supervisiors:", 
                    "Choose one from the list, use the number!",
                    ["A","B","X"])     

print(k)
print(sup)

Output:

# intInputCheck("INPUT -> ","Please only input integers")
INPUT -> a
Please only input integers
INPUT -> b
Please only input integers
INPUT -> 99

# intInputCheck("Possible supervisiors:", "Choose one from the list, use the number!", 
#               ["A","B","X"])  
Possible supervisiors:
 1 : A
 2 : B
 3 : X
Choice -> 8
Choose one from the list, use the number!
Possible supervisiors:
 1 : A
 2 : B
 3 : X
Choice -> 6
Choose one from the list, use the number!
Possible supervisiors:
 1 : A
 2 : B
 3 : X
Choice -> 2

The results:

# k
99

# sup
(2, 'B')
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thank you for your help, I will try to implement this now, one question though, what does "options=[]" do inside the function parameters? I have never seen it before, is it similar to "*args" where it allows for no input? – James Green Nov 01 '18 at 20:22
  • 1
    Also I would just like to point out that the "test = range" should have a +1 as it doesn't include the third number (includes 1,2 but not 3) – James Green Nov 01 '18 at 20:26
  • 1
    @JamesGreen fixed my range - thats what I get when I try to use 1based :) - the `options=[]` is a default parameter - it allows the function to be called with 1 less parameter and options will be automatically be set to be an empty list: `intInputCheck("INPUT -> ","Please only input integers")` - see [default-values-for-function-parameters-in-python](https://stackoverflow.com/questions/13195989/default-values-for-function-parameters-in-python) – Patrick Artner Nov 01 '18 at 20:36