1

Today i made this function to try and understand the try/except. If i run this code it should ask for a positive integer x, to roll a dice function x times. I made the code below but it seems to never get in the "ValueError". I'd like to check if the input (n) is first an integer (digit in the string) and secondly if the integer is positive. if one of these occur, raise the exception.

How can i fix it that it works correctly?

def userInput():
    while True:
        try:
            n=input("How many times do you want to roll the dice? ")
            if not n.isdigit():
                raise TypeError
            
            n = int(n)
            if n < 0:
                raise ValueError
            else:
                break

        except ValueError:
            #if type is integer but not a positive integer
            print("Please enter a positive integer")
    
        except TypeError:
            #if type is not an integer
            print("Only positive integers allowed")
    
return n
2
  • 1
    "-" is not a digit, so you raise the TypeError before you reach the next check. isdigit is the wrong check anyway. You can check this with the superscript 2. '²'.isdigit() is true, but int('²') will fail. You might want to read "Digits int() doesn’t dig" Commented Oct 12, 2022 at 17:09
  • Hi, I get what you mean that "-" is not a digit so "-2" would mean it first sees the "-" and throws the typeError, but how can i change it that it will first check if its a digit (or int) and if its not an int to throw a typeError, i also tried: """if not type(n) is int: but that also does not work since i used to do int(input()) Commented Oct 12, 2022 at 17:18

2 Answers 2

1

Stripping out the - doesn't address the issue of some digits not actually being integers, as Matthias's link describes. You would be much better off trying to convert to int without checking isdigit(). If the input can't be converted to an integer, this raises a ValueError with the message "invalid literal for int() with base 10: '...'".

If you want to raise a ValueError with a custom message for your positive number check, you can do raise ValueError("Please enter a positive integer")

Then, in the except block, you can access this message through the .args attribute of the exception:

def userInput():
    while True:
        try:
            n = int(input("How many times do you want to roll the dice? "))
            if n < 0:
                raise ValueError("Please enter a positive integer")
            else:
                return n # You probably want to do this instead of just break out of the loop

        except ValueError as ex:
            print(ex.args[0])

Calling the function gives:

How many times do you want to roll the dice? -5
Please enter a positive integer

How many times do you want to roll the dice? abc
invalid literal for int() with base 10: 'abc'

How many times do you want to roll the dice? 1

To be clear, it would be cheaper to simply print the error message for non-positive integers instead of raising an error only to catch it immediately. That way, you can modify the message that is printed when the int() conversion fails. Consider:

def userInput():
    while True:
        try:
            n = input("How many times do you want to roll the dice? ")
            n = int(n)
            if n < 0:
                print("Please enter a positive integer")
            else:
                return n # You probably want to do this instead of just break out of the loop

        except ValueError as ex:
            print(f"Hey, {n} is not a valid integer!")

which would print:

How many times do you want to roll the dice? abc
Hey, abc is not a valid integer!

How many times do you want to roll the dice? 10.5
Hey, 10.5 is not a valid integer!

How many times do you want to roll the dice? -100
Please enter a positive integer

How many times do you want to roll the dice? 100
Sign up to request clarification or add additional context in comments.

9 Comments

I get the point you made indeed, so i was right with trying to let int(input()) handle it in the first place. I just didnt know how to handle it properly. I'd like to ask how the print(ex.args[0]) exactly works, since i'd like it to print "not a positive integer", instead it now prints invalid literal.....
@itzMeep that's right. In fact, I would probably avoid raising an error just to catch it immediately, and just print the message out. See the edit
i tried your edit but i got: UnboundLocalError: local variable 'n' referenced before assignment
@itzMeep re. "how print(ex.args[0]) works: when you (or python) raise an exception, the message is actually the first argument to the constructor. All args to the constructor are saved in the args attribute, so when you do ex.args[0], you get the first argument.
@itzMeep I'm not sure how you got that error, n isn't referenced anywhere before assignment.
|
0

Your code works perfectly for positive numbers, to handle negative numbers, you need to modify at one place

if not n.lstrip('-').isdigit():

I hope this solves your problem

4 Comments

This doesn't address the problem Matthias mentioned in their comment above
if you remove the "-" and just checks whats after it it will look if its a digit, thats pretty much all i needed. Is there a better way to check it you think?
@itzMeep see the link Matthias shared. Also, this would accept an input like ---100, but then the int(n) would throw a ValueError so why not just let int(n) handle it instead of introducing an extra check? See the answer I just added
Just try to convert the value to integer with int. This will give you a TypeError if something goes wrong. If you want to change that to a ValueError - a bad idea in my opinion - you could raise a ValueError in the exception.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.