0

I'm getting input at run time. If first attempt itself correct input given means I'm not getting the error. Otherwise it is showing can't unpack non-iterable error.

I can see it is sending None if recursive method called once. Even it prints value before return, but after receiving it shows None.

class Game:
    def set_val(self):
        try:
            p1=input("Enter player 1 name:")
            p2=input("Enter player 2 name:")
            goal=int(input("Enter a number to set goal:"))
            if p1 is None or p2 is None or goal is None:
                print("Please give proper input")
                self.set_val()
            else:
                print(p1,p2,goal)
                return p1,p2,goal
        except:
            print("Please give proper input")
            self.set_val()
G=Game()

p1,p2,goal=G.set_val()
print(p1,p2,goal)

OUTPUT:

Enter player 1 name:s
Enter player 2 name:c
Enter a number to set goal:s
Please give proper input
Enter player 1 name:s
Enter player 2 name:v
Enter a number to set goal:2
s v 2
Traceback (most recent call last):
  File "D:\test.py", line 18, in <module>
    p1,p2,goal=G.set_val()
TypeError: cannot unpack non-iterable NoneType object

I can assume it because of recursive calls, but not able to figure it out why. Please explain give a solution to get all input values without error.

Vanjith
  • 520
  • 4
  • 23

2 Answers2

3

Recursion has its uses, but using it to start over is not one of them. Naked except is also bad.

If you need to loop, use a loop.

If you need to catch an exception, catch the expected exception. That way if an unexpected exception occurs, you can see and deal with the bug.

Example:

class Game:
    def set_val(self):
        while True:
            p1=input("Enter player 1 name:")
            if p1: break
        while True:
            p2=input("Enter player 2 name:")
            if p2: break

        # Loop until good input
        # int() will throw ValueError if input is not convertible to int.
        while True:
            try:
                goal=int(input("Enter a number to set goal:"))
                break # break from the loop if no exception
            except ValueError:
                print("Please give proper input")

        return p1,p2,goal

G=Game()

p1,p2,goal=G.set_val()
print(p1,p2,goal)
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
2

1) Never do a general exception to catch everything.

2) You should NOT use recursion for user input. It consumes stack for no reason. Just use a while loop. Basically recursion is not designed to keep repeating if something fails. It is designed to dive into something and eventually come back.

3) Make sure you properly space your code. This didn't cause the issue but it does make the code hard to read. You should have a space before and after operators (i.e. =) and a space after commas with multiple elements (i.e. (1, 2, 3))

That being said, when you do recursion, you need to return the recursive call:

class Game:
    def set_val(self):
        try:
            p1 = input("Enter player 1 name:")
            p2 = input("Enter player 2 name:")
            goal = int(input("Enter a number to set goal:"))
            if p1 is None or p2 is None or goal is None:
                print("Please give proper input")
                return self.set_val()
            else:
                print(p1, p2, goal)
                return p1, p2, goal
        except:
            print("Please give proper input")
            return self.set_val()
G = Game()

p1, p2, goal = G.set_val()
print(p1, p2, goal)

Also your if can be shortened to this:

if p1 and p2 and goal: