Reputation: 7838
I had to write the following function to fail gracefully when trying to parse a string to an integer. I would imagine Python has something built in to do this, but I can't find it. If not, is there a more Pythonic way of doing this that doesn't require a separate function?
def try_parse_int(s, base=10, val=None):
try:
return int(s, base)
except ValueError:
return val
The solution I ended up using was a modification of @sharjeel's answer. The following is functionally identical, but, I think, more readable.
def ignore_exception(exception=Exception, default_val=None):
"""Returns a decorator that ignores an exception raised by the function it
decorates.
Using it as a decorator:
@ignore_exception(ValueError)
def my_function():
pass
Using it as a function wrapper:
int_try_parse = ignore_exception(ValueError)(int)
"""
def decorator(function):
def wrapper(*args, **kwargs):
try:
return function(*args, **kwargs)
except exception:
return default_val
return wrapper
return decorator
Upvotes: 107
Views: 90245
Reputation: 21441
Actually there is a "built-in", single line solution that doesn't require introducing a helper function:
>>> s = "123"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
123
>>> s = "abc"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None
>>> s = ""
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None
>>> s = "1a"
>>> i = int(s) if s.isdecimal() else None
>>> print(i)
None
In case you need to support negative numbers, too, the following extension considers one (or more) leading dashes/minus as the algebraic sign for negative numbers:
>>> s = "-123"
>>> i = int(s) if s.split("-", 1)[-1].isdecimal() else None
>>> print(i)
-123
See also:
Upvotes: 57
Reputation: 629
PHP has a smart flexible integer casting algorithm.
Here is a similar attempt in Python.
def parseInt(txt: str) -> int:
"""
PHP like integer parsing.
Args:
txt (str): string to parse.
Returns:
int: found integer.
:Example:
>>> parseInt("")
0
>>> parseInt("-")
0
>>> parseInt("-a")
0
>>> parseInt("-456as")
-456
>>> parseInt("123456z654")
123456
"""
if not len(txt):
return 0
result = ""
if txt[0] == "-":
result = "-0"
txt = txt[1:]
for char in txt:
if char.isdigit():
result += char
else:
break
else:
return 0
return int(result)
Upvotes: 0
Reputation: 389
Depending on the circumstances, the following might fit the needs of some readers: leveraging short-circuiting, you can obtain either False
or an actual integer, and you can check for its type.
pos = s.strip().lstrip("-")
number = pos.isdecimal() and pos.isdigit() and int(s)
if number is not False:
Just remember that False == 0
yields True
. So, don't straight up compare it to an integer without first checking that is not False
. Another option would be as follows,
pos = s.strip().lstrip("-")
if pos.isdecimal() and pos.isdigit() and (int(s) == test_number):
Upvotes: 0
Reputation: 617
This could be another alternative for parsing string to int
while True:
try:
n = input("Please enter an integer: ")
n = int(n)
break
except ValueError:
print("No valid integer! Please try again ...")
print("Great, you successfully entered an integer!")
Upvotes: 1
Reputation: 6015
This is a pretty regular scenario so I've written an "ignore_exception" decorator that works for all kinds of functions which throw exceptions instead of failing gracefully:
def ignore_exception(IgnoreException=Exception,DefaultVal=None):
""" Decorator for ignoring exception from a function
e.g. @ignore_exception(DivideByZero)
e.g.2. ignore_exception(DivideByZero)(Divide)(2/0)
"""
def dec(function):
def _dec(*args, **kwargs):
try:
return function(*args, **kwargs)
except IgnoreException:
return DefaultVal
return _dec
return dec
Usage in your case:
sint = ignore_exception(ValueError)(int)
print sint("Hello World") # prints none
print sint("1340") # prints 1340
Upvotes: 61
Reputation: 31
myList = ['12', '13', '5', 'hope', 'despair', '69','0', '1.2']
myInts = [int(x) for x in myList if x.isdigit()]
Upvotes: 2
Reputation: 3
def parseint(string):
result = '0'
for x in string:
if x.isdigit():
result+=x
else:
return int(result)
return int(result)
Upvotes: -3
Reputation: 14361
def intTryParse(value):
try:
return int(value), True
except ValueError:
return value, False
Upvotes: 48
Reputation: 72978
That's the pythonic way. In python, it's customary to use EAFP style - Easier to Ask Forgiveness than Permission.
That means you'd try first, and then clean up the mess if necessary.
Upvotes: 26
Reputation:
int() is the built-in and pythonic way, just like you have there.
It's usually easier and more common to use it directly though:
def show_square(user_input):
"""Example of using int()."""
try:
num = int(user_input, 10)
except ValueError:
print "Error" # handle not-an-integer case
# or you may just want to raise an exception here
# or re-raise the ValueError
else:
print "Times two is", num * 2
def another_example(user_input):
try:
num = int(user_input, 10)
except ValueError:
num = default
print "Times two is", num * 2
Upvotes: 2
Reputation: 93173
I would go for:
def parse_int(s, base=10, val=None):
if s.isdigit():
return int(s, base)
else:
return val
But it's more or less the same thing.
Upvotes: 16
Reputation: 49833
No, it is already perfect. The val
parameter could be better named default, though.
Documented in the official docs simply as int(x) -- x converted to integer
Upvotes: 7