-1

Why is no ValueError raised on this try / except when isalpha should fail.

I know that isalpha returns false if given a number

In [9]: ans = input("Enter a Letter")
Enter a Letter4

In [10]: ans.isalpha()
Out[10]: False

How do I get the value error if they supply a number instead of a y or n? Because if the try is false shouldn't it stop being true and not print my trajectory?

import sys

v0 = float(input("What velocity would you like? "))
g = float(input("What gravity would you like? "))
t = float(input("What time decimal would you like? "))

print("""
    We have the following inputs.
       v0 is %d
       g is  %d
       t is  %d
    Is this correct? [Y/n]
""" % (v0, g, t))
while True:
    try:
        answer = input("\t >> ").isalpha()
        print(v0 * t - 0.5 * g * t ** 2)
    except ValueError as err:
        print("Not a valid entry", err.answer)
        sys.exit()
    finally:
            print("would you like another?")
            break

For example if the user types 5 not a y or n still gets an answer

$ python3 ball.py 
What velocity would you like? 2
What gravity would you like? 3
What time decimal would you like? 4

    We have the following inputs.
       v0 is 2
       g is  3
       t is  4
    Is this correct? [Y/n]

     >> 5
-16.0
would you like another?
sayth
  • 6,696
  • 12
  • 58
  • 100
  • 2
    As you've already stated, `isalpha()` returns `True | False`. Why would you expect it to raise a `ValueError`? – SiHa Sep 21 '16 at 13:26
  • @SiHa from several SO example showing answer that if an int is false it will raise a valueError for example http://stackoverflow.com/a/8075959/461887. Figured the reverse would then be true – sayth Sep 21 '16 at 13:33
  • But that's completely different. In that situation, they are trying to cast a non-numeric string to an int, which raises an exception because it is not possible. Calling `'4'.isalpha()` will return `False` but no exception will be raised because *no exception has occurred* - the function call was successful. I would suggest reading up a bit more on `try...except` to fully understand the concept. – SiHa Sep 21 '16 at 13:38
  • @SiHa so is it possible to do the reverse which i was trying to cast an int to a string and get same failure or is the int special in that respect? Which will be where I have screwed up my intent. – sayth Sep 21 '16 at 13:42
  • 1
    But you are *not* trying to cast an int to a string, you are calling a library function to tell you if it is a letter of the alphabet. As mentioned below, it is generally a bad idea to use exceptions to control program flow. You have a boolean from your `isalpha()` call, use it in an `if` statement, and forget about exceptions here. P.S. if you *did* try to cast an int to a string, that would not raise an exception anyway - `'4'` is a perfectly valid string :) – SiHa Sep 21 '16 at 13:46
  • 1
    @SiHa thanks, the example was contrived from a problem I had previously solved just to use and learn try and except I thought a user entering an int when a string was desired was a good use case for that. Ultimately not – sayth Sep 21 '16 at 13:53

4 Answers4

3

except ValueError as err: only happens when there is a ValueError thrown. The value of answer is False, but that is just an arbitrary boolean value, not an error.

See ValueError documentation for examples of things that are errors.

In your case, simply test:

answer = input("\t >> ")
if answer.isalpha():
    print(v0 * t - 0.5 * g * t ** 2)
    break
njzk2
  • 38,969
  • 7
  • 69
  • 107
  • I searched SO before posting and seems a mixed opinion to whether one should prefer to use conditional logic versus try / except. In this case it was a contrived problem for me just to use try and except if a user didn't enter a "Y" or "y" I gave up and just tried to get an error if it wasn't a letter – sayth Sep 21 '16 at 13:38
  • 2
    `Explicit is better than implicit.` suggests that conditional logic should be preferred over `try / except`. Can you post a couple links where this is discussed. – Craig Burgler Sep 21 '16 at 13:44
  • Here is one question I have closed a few SO tabs off in posting, however one answer has 63 for try except and the other 61 for conditional http://stackoverflow.com/q/2020598/461887 especially see some of the comments which are directing to use the try except as the preference – sayth Sep 21 '16 at 13:47
  • 1
    The one with 63 is catching an exception from an external function, not from the evaluation of a local variable. A function throwing an exception is actually preferred to it returning `None` to indicate special meaning, as per `Effective Python`. But that case is very different than evaluating a variable – Craig Burgler Sep 21 '16 at 13:51
  • 2
    @sayth in the case you mention, I favor the exception. The `simulate` function returns a boolean in normal exception, and the `except` catches unexpected failures. – njzk2 Sep 21 '16 at 13:53
2

In general you should prefer to use normal control flow logic to handle a range of user input rather than raising/catching exceptions.

Craig Burgler
  • 1,749
  • 10
  • 19
  • The print section works fine, it appears my inability to cast an int to string for failure and ValueError is my undoing. In testing for isalpha() I only received boolean. – sayth Sep 21 '16 at 13:45
  • 1
    Can you give an example of values for `v`, `g`, and `t`, and what is printed, when the user inputs a number? The statement `print(3 * '4' - 0.5 * 5 * '4' ** 2)`, for example, raises a `TypeError`. – Craig Burgler Sep 21 '16 at 13:47
  • I have it in my updated question, for with ints of 2 3 4 and returns -16.0 – sayth Sep 21 '16 at 13:50
  • OK I misunderstood. I thought `t` referred to the user input. – Craig Burgler Sep 21 '16 at 14:03
1

You need to raise the error yourself. There is no exception raised by typing in something that you don't prefer:

try:
    answer = input("\t >> ").isalpha()
    if not answer:
        raise ValueError
    print(v0 * t - 0.5 * g * t ** 2)
except ValueError as err:
    print("Not a valid entry", err.answer)
    sys.exit()
joel goldstick
  • 4,393
  • 6
  • 30
  • 46
0

Posting an answer for clarity trying to provide a way to be more consistent and explicit with the treatment of strings and int's. By using isinstance I declare to a person reading my code explicitly what my values are to be hopefully improving readability.

answer = input("\t >> ")
if isinstance(int(answer), int) is True:
    raise ValueError("Ints aren't valid input")
    sys.exit()
elif isinstance(answer, str) is True:
        print(v0 * t - 0.5 * g * t ** 2)
else:
    print("Ok please ammend your entries")

Should I have differing requirements later this could easily be abstracted into a function, which because isinstance allows checking against multiple types increases flexibility.

Reference How to properly use python's isinstance() to check if a variable is a number?

def testSomething(arg1, **types):
    if isintance(arg1, [types]):
        do_something
Community
  • 1
  • 1
sayth
  • 6,696
  • 12
  • 58
  • 100