#post
python-string-check-if-contains-integer
While validating user input (in the form of URL query params), I needed to check if a query param value (which arrives as a string) was a string representation of an integer so it could be safely treated as an int.
I settled on isdigit()
(as suggested here), which confirms the string only contains digit characters. No .
, no -
, just digits.
Since I’m looking for a non-negative integer and not concerned about the edge case of isdigit
returning True for sub/superscript digits int
can’t handle, that was perfect:
for key, val in value.items():
if not isinstance(key, str) or not str.isdigit(key.strip()):
raise ValidationError(
f"Invalid key '{key}'. Must be a string containing a non-negative integer representing an experiment day number."
)
This may be less of a Pythonic (or efficient) approach than this suggestion to simply try the integer conversion via int()
and deduce it isn’t an int if a ValueError
occurs:
def represents_int(s: str) -> bool:
try:
int(s)
except ValueError:
return False
else:
return True
>>> print(represents_int("+123"))
True
>>> print(represents_int("10.0"))
False
The advantage of that approach is that it dodges all the tricky special cases you’d otherwise need to check and truly answers the question that matters (can I safely convert this string to an int
)? To quote the top-voted answer to the same question here:
A string is a string. It is neither an int nor a float. It is a string. To check if a string can be converted into an int or a float, you can just do the conversion and deal with the consequences if it fails (
ValueError
). It will be much faster than trying to faff about with regexps, which can get pretty outrageous once you realise that you also need to handle NaNs, infinities, scientific notation, etc.
I’m still getting used to Python’s preference for “asking for forgiveness rather than permission” (i.e. try + catch exceptions) as opposed to “looking before you leap”, which I find more intuitive.