0

I am trying to check if my input is a string with try-except block. The function runs without an error. However it checks if the input is an integer, not string. How can I inverse this?

def lexicon(word):
    while True:
        try:
            a=str(input(word))
            print("Input is a string. string = ", a)
        except ValueError:
            print("Oops..Input is not supposed to be a number. Try again!")
    return a
b=lexicon("Enter the word you'd like: ")
5
  • Does this answer your question? How to find out if a Python object is a string? Commented Nov 17, 2020 at 4:49
  • 1
    The input function always returns a string, so checking if it is a string is pretty pointless. What exactly do you want to do? Commented Nov 17, 2020 at 4:52
  • I can't even understand why he has passed the object parameter into input? And @Antimon pointed out correctly that he has converted every word to string so it's pointless to use try-except block for numbers as they are going to be converted to string anyways.. Problem statement is not clear Commented Nov 17, 2020 at 4:54
  • @Raghav not only that, but str(input(...)) is redundant since the return value of input is always a string anyway. This code would make sense if it was int(input(...)), but OP would need to clarify here. Commented Nov 17, 2020 at 5:01
  • @Antimon If the input is an integer I want to tell the user that its an error and they need to enter a string as the input Commented Nov 17, 2020 at 13:25

2 Answers 2

3

As discussed with user pavel in the comments to his answer, there are two different styles to code for a problem like this: EAFP ("Easier to Ask for Forgiveness than Permission"), meaning that you make your code work on an assumption and take action if it fails; and LBYL ("Look Before You Leap"), in which you first check whether your assumption is true, and then choose the appropriate action to take.

The try/except route is EAFP, since it just executes the code in the try block without bothering to first check whether it would work. If you want to do it in LYBL style, you would explicitly need to ascertain whether the user input is a string representation of a numeric value, and then act accordingly. I'll provide skeletal code for both approaches below. However, note that Python is a little weird compared to other languages in that it seems to have a certain cultural favour for EAFP.

Also, since you are only asking about checking for integers, I will focus on that here. This means that the code will accept floats as valid inputs.

EAFP: try/except

The problem that presumably trips you up is that input always returns a string, so testing if it is a string is nonsensical and will always yield True. However, note that try/except is only an abrigded version of error handling that you can do in Python; the full version is try/except/else/finally. The else block takes effect if no except blocks are executed, and finally is always run at the end. So you could check whether your input is an integer, and make the program raise a failure if that check succeeds. I admit however that this does seem a bit backwards.

try:
    a = int(input())
except ValueError:
    # do whatever
else:
    raise ValueError("Input must not be an integer")

LBYL: if/else

str objects have several methods to test their contents without having to run into errors. For example, .isalpha() checks if all characters are in the alphabet (which returns False however if you include spaces and special characters); isnumeric() checks whether the string is a representation of a number; etc. See a full list here. So depending on what kind of inputs you want to allow, you would need to use one of these methods, or a combination of them, in an if block. The code below essentially does the same thing as the try/except/else version above, using .isdigit() which returns True if all characters in the string are digits (i.e., the same kind of input for which int(a) would succeed).

Note also that I am making use of the new assignment operator := in this code, which is new to Python 3.8. This way, you don't need to explicitly assign the variable a first, however it's a bit harder to catch where the code actually executes an input() function. If you code for backwards compatibility, or don't like the look of this, you'd have to go with the classical a = input() first.

if (a := input()).isdigit():
    raise ValueError("Input must not be an integer")

# do whatever
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for the detailed, clear explanation!
2

If you want specifically to check the value type of the string, you're better off using if/else and isinstance:

if not isinstance(word, str):
    raise TypeError(f"Expecting a string as a value, not {type(word)}.")
else:
    #do something

5 Comments

Note however that Python favours the EAFP style ("Easier to Ask for Forgiveness than Permission"), so try/except would probably be considered more idiomatic.
@Antimon, I guess, that really depends on what your code is doing. If the variable is being used immediately or very close to where it's declared, try-except sounds like a good idea, but if the variable is declared early and is only used much later in execution, I think it's better to do an early check and raise an error.
Also I think that if isinstance() and if not isinstance() are both very idiomatic in Python but I may be wrong.
How would you do this with try/except block?
agree with pavel, better to avoid try/except where it is not needed as it is bad for performance. Testing with isinstance() is very pythonic

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.