To determine if a string represents a numeric value (integer or float) in Python, you can use the following approaches. Each method addresses edge cases like leading/trailing whitespace, scientific notation (e.g., 1e3
), and special values like NaN
or Inf
.
1. Using Exception Handling (Recommended)
Attempt to convert the string to a float
and catch errors. This handles most valid numeric formats:
def is_number(s):
try:
s = s.strip() # Remove leading/trailing whitespace
if not s:
return False # Empty string after stripping
num = float(s)
# Optional: Exclude NaN/Inf (uncomment to disable)
# if math.isnan(num) or math.isinf(num):
# return False
return True
except ValueError:
return False
Example Usage:
print(is_number("123")) # True (int)
print(is_number("-123.45")) # True (float)
print(is_number("1e3")) # True (scientific notation)
print(is_number(" 123.45 ")) # True (whitespace stripped)
print(is_number("NaN")) # True (by default; returns False if uncommented)
print(is_number("12a3")) # False
print(is_number("")) # False
2. Using Regular Expressions
Match numeric patterns (integers, floats, scientific notation) with a regex. This avoids exceptions but requires precise pattern definition:
import re
def is_number_regex(s):
pattern = r"^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$"
return bool(re.fullmatch(pattern, s.strip()))
Regex Breakdown:
^[+-]?
: Optional leading+
or-
.\d+\.?\d*
: Matches integers (123
) or floats with digits before the decimal (123.
,123.45
).|\.\d+
: Matches floats starting with.
(e.g.,.45
).(?:[eE][+-]?\d+)?$
: Optional scientific notation (e.g.,1e3
,-2.5E-4
).
Example Usage:
print(is_number_regex("123")) # True
print(is_number_regex(".45")) # True
print(is_number_regex("123.45")) # True
print(is_number_regex("1e3")) # True
print(is_number_regex("12a3")) # False
print(is_number_regex("NaN")) # False (regex excludes non-numeric strings)
Key Differences
Method | Pros | Cons |
---|---|---|
Exception Handling | Handles all valid Python numeric formats. | Allows NaN /Inf by default. |
Regex | Explicit control over valid patterns. | Complex regex; may miss edge cases. |
Handling Integers vs. Floats
To distinguish between integers and floats, extend the exception-handling method:
def is_integer(s):
try:
s = s.strip()
if not s:
return False
num = float(s)
# Check if the float is an integer and the string lacks a decimal point
return num.is_integer() and "." not in s
except ValueError:
return False
print(is_integer("123")) # True
print(is_integer("123.0")) # False (contains '.')
print(is_integer("123.5")) # False
Final Recommendation
Use exception handling for simplicity and coverage of edge cases. If you need to exclude NaN
or Inf
, uncomment the relevant checks. For strict pattern control (e.g., disallow leading zeros), use the regex method.