Check if a String is a Number in Python

By James L.

Checking if a string represents a number is a fundamental Python skill. It unlocks numerous possibilities, such as validating user input, seamlessly handling file data, and performing accurate calculations.

In this guide, we will discuss the following approaches to check if a string is a number in Python:

  • Using try-except block
  • Using isdigit() method
  • Using isnumeric() method
  • Using regular expression

#1 Using try-except block 

In Python, a try-except block is used to handle exceptions (errors) that may occur during the execution of a program. 

In this method, we attempt to convert a string to a number using the float() method. If the conversion is successful, it means the string is a number. Otherwise, it’s not a number.

Here’s an example:

def is_number(str):
    # Check if a string is a number using try-except block
    try:
        x = float(str)
        # Return True if the conversion to float is successful
        return True
    except ValueError:
        # Return False if the conversion fails
        return False


print(is_number("22"))       # True -> Integer
print(is_number("3.14"))     # True -> Float
print(is_number("-35"))      # True -> Negative Integer
print(is_number("-44.71"))   # True -> Negative float
print(is_number("hello"))    # False -> String with alphabets
print(is_number("5e7"))      # True -> Scientific Notation
print(is_number("   22  "))
# True -> Integer with leading and trailing whitespace
print(is_number("3a4"))      # False -> Alphanumeric string
print(is_number("5.6.7"))    # False -> Invalid float with multiple dots
print(is_number(""))         # False -> Empty string
print(is_number(" "))        # False -> Whitespace
print(is_number("1,000"))    # False -> Comma in integer
print(is_number("300 000"))  # False ->Integer with whitespace in between

The try-except block handles a wide range of number formats, including integers, floats, negative, and even scientific notation. It also handles unexpected input scenarios such as leading/trailing whitespaces, alphanumeric strings, or strings with multiple dots. 

The versatility of this approach makes it a reliable choice for validating numeric strings in diverse situations. However, the try-except approach is slower than other methods, especially for non-numbers. Benchmarks show the try-except approach can be slower for non-numbers, but faster for numbers, which are more likely in practice. 

#2 Using isdigit() method

The isdigit() method checks if a string consists of only digits. It returns True if all characters in the string are digits (0-9), and False otherwise.

For example:

def is_number(str):
    return str.isdigit()


print(is_number("22"))     # True
print(is_number("hello"))  # False

Handling decimal numbers (float)

The isdigit() method only checks for digits (0-9) in a string. This means it doesn’t recognize decimal numbers like "3.14", even though we might consider them numeric. 

If you need to consider numbers with decimal points as numeric values, you must handle them explicitly.

You can use the replace() method to remove the decimal point and check if the resulting string consists only of digits. 

Here’s an example:

def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of ‘.’ if present
    str = str.replace('.', '', 1)
    return str.isdigit()


print(is_number("22"))     # True
print(is_number("hello"))  # False
print(is_number("3.14"))   # True
print(is_number("2.6.3"))  # False

In the example above, we first use the strip() method to remove the leading and trailing whitespace. 

Then, we use the replace() method to replace the first occurrence of the dot ('.') in the string str with an empty string ('').

The third argument 1 specifies that only the first occurrence should be replaced. This is important because if there are multiple dots in the string, you want to retain the rest. This allows you to correctly identify the string with one decimal point as a number. However, strings with multiple decimal points (e.g. "192.168.1.1") will be considered non-numeric. 

Handling negative numbers

To handle negative numbers, you can extend the check by allowing a minus sign at the beginning of the string. 

Here’s an updated example:

def is_number(str):
   # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)

    # Check if the first character is "-". If yes, remove it
    if str[0] == "-":
        str = str[1:]

    # Check if the remaining string is composed of only digits
    return str.isdigit()


print(is_number("22"))     # True
print(is_number("-24"))    # True
print(is_number("--66"))   # False
print(is_number("+29"))    # False

In the example above, we check if the first character in the string is "-". If it is, we remove it by using the slice notation. The slice notation str = str[1:] extracts the substring starting from the index 1 to the end of the string. Then, we check if the string contains only digits.

If you want to handle the positive sign ("+") in your code, you can further modify the is_number() function to consider the possibility of a positive sign at the beginning of the string.

Here is an updated version of the code:

def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)

    # Check if the first character is '+' or '-'. If yes, remove it
    if str[0] in ["+", "-"]:
        str = str[1:]

    return str.isdigit()


print(is_number("22"))     # True
print(is_number("-24"))    # True
print(is_number("--66"))   # False
print(is_number("+29"))    # True

Handling scientific notation numbers

If you want to handle scientific notation numbers, you can further modify the is_number() function to handle scientific numbers.

Here’s an updated code:

def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)

    # Check if the first character is '+' or '-'. If yes, remove it
    if str[0] in ["+", "-"]:
        str = str[1:]

    # Convert the string to lowercase to handle 'e' and 'E'
    str = str.lower()

    # check if the string is a scientific notation number
    parts = str.split('e', 1)

    if len(parts) == 2 and parts[0].isdigit() and (parts[1].isdigit() or (parts[1][0] in ["+", "-"] and parts[1][1:].isdigit())):
        return True

    return str.isdigit()


print(is_number("22"))     # True
print(is_number("hello"))  # False
print(is_number("2e5"))    # True
print(is_number("-3e7"))   # True
print(is_number("7e-5"))   # True
print(is_number("4E7"))    # True

Handling scientific notation numbers using the isdigit() method can be tricky. First, we convert the string to lowercase to handle both 'e' and 'E'

Then, we split the string at the first occurrence of 'e'. The result is stored in the parts list. If the length of the parts is 2 and the first part (before 'e') consists of digits, and the second part (after 'e') consists of digits or starts with '+' or '-', followed by digits, then the function returns True, indicating the string is a valid scientific notation number. 

If the first part (before 'e')  contains a negative sign, it has already been removed in a previous step. If the conditions for scientific notation are not met, the function falls back to check if the entire string consists of digits using the isdigit() method.

#3 Using isnumeric() method

The isnumeric() method checks if a string consists of only numbers. It returns True if all characters in the string are numbers, and False otherwise.

For example:

def is_number(str):
    return str.isnumeric()


print(is_number("22"))     # True
print(is_number("hello"))  # False

Differences between isdigit() and isnumeric() method

In Python, both isdigit() and isnumeric() methods are used to check if all characters in a string are numeric, but they differ in their level of strictness and the type of characters they consider valid. 

Here’s a breakdown of their key differences.

isdigit():

Stricter: Only considers characters classified as Unicode digits (0-9)

Example: "123" returns True, "\u0031" returns True (Unicode for 1),  "\u2165" returns False (Unicode for Roman numeral )

isnumeric():

More inclusive: Considers a wide range of characters including:

  • Unicode digits (0-9)
  • Fractions
  • Some specific characters like Roman numerals and superscripts/subscripts

Example: "123" returns True"\u0031" returns True (Unicode for 1), "¼" returns True, "\u2165" returns True (Unicode for Roman numeral )

Handling decimal point numbers (float)

The isnumeric() method, like isdigit(), is also limited to checking for numeric characters in a string. This means it won’t recognize decimal numbers like "3.14" as valid.

To handle decimal point numbers, you can use the replace() method to remove the decimal point and check if the resulting string consists only of digits. 

Here’s an updated code:

def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)
    return str.isnumeric()


print(is_number("22"))     # True
print(is_number("hello"))  # False
print(is_number("3.14"))   # True

In the example above, we first use the strip() method to remove the unnecessary leading and trailing whitespace. 

Then, we use the replace() method to remove the first occurrence of the dot ('.') in the string str with an empty string ('').

The third argument 1 specifies that only the first occurrence of the dot ('.') should be replaced. 

Handling negative numbers

To handle negative numbers, you can extend the check by removing a minus sign ('-') at the beginning of the string if present. 

Here’s an updated code:

def is_number(str):
   # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)

    # Check if the first character is "-". If yes, remove it
    if str[0] == "-":
        str = str[1:]

    # Check if the remaining string is composed of only digits
    return str.isnumeric()


print(is_number("22"))     # True
print(is_number("-24"))    # True
print(is_number("--66"))   # False
print(is_number("+29"))    # False

In the example above, we use the slice notation str = str[1:] to extract the substring starting from the index 1 to the end of the string.

If you want to handle the positive sign ('+') in your code, you can further modify the is_number() function to consider the possibility of a positive sign at the beginning of the string.

Here is an updated version of the code:

def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Remove the first occurrence of '.' if present
    str = str.replace('.', '', 1)

    # Check if the first character is '+' or '-'. If yes, remove it
    if str[0] in ["+", "-"]:
        str = str[1:]

    return str.isnumeric()


print(is_number("22"))     # True
print(is_number("-24"))    # True
print(is_number("--66"))   # False
print(is_number("+29"))    # True

Handling scientific notation numbers

Handling scientific notation numbers using the isnumeric() method is not a good idea because it accepts digits and their Unicode representations from various languages.

Even adding checks for 'e' or 'E' isn’t foolproof. It will fail if the string contains mixed exponential and characters from different languages like "2E๑5".

#4 Using regular expression

A regular expression (regex) is a powerful tool that allows us to find and manipulate specific patterns in a string. It can extract valuable information, validate data, and even transform text in creative ways.

You can use a regular expression to check if a string is a number. It makes sense to use regular expressions if you already know what kind of number format you are looking for.

Checking if a string is an integer

Below is a code example that checks if a string is an integer:

import re


def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Define a regular expression pattern for an integer
    pattern = re.compile(r'^\d+$')

    # Return True if the pattern matches the entire string
    return bool(pattern.match(str))


print(is_number("22"))     # True
print(is_number("hello"))  # False

First, you need to import the re module to use regular expressions in Python.

In the is_number() function:

  • We first define the pattern using re.compile() method. The re.compile() method takes a regular expression pattern as a string and compiles it to a reusable Pattern object.
  • Then, we call the match() method on the compiled pattern object with the string to be checked. The match() method attempts to match the compiled pattern against the beginning of the given string.
  • If the match() method returns a Match object (meaning the pattern matches the beginning of the string), the bool conversion returns True, indicating the string is a valid integer.
  • If the match()method returns None (no full match), the bool conversion returns False, indicating the string is not a valid integer.

In the regular expression '^\d+$':

^: Asserts the start of the string. The ^ indicates the start of the string.

\d+: Matches one or more digits. \d represents any digits (0-9), and the + quantifier means “one or more”.

$: Asserts the end of the string. The $ indicates the end of the string.

This pattern ensures that the string starts with a digit, contains one or more digits, and ends with a digit.

Handling optional positive (+) or (-) sign 

Below is a code that checks if a string is an integer with an optional positive or negative sign:

import re


def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Define a regular expression pattern
    pattern = re.compile(r'^[+-]?\d+$')

    # Return True if the pattern matches the entire string
    return bool(pattern.match(str))


print(is_number("22"))     # True
print(is_number("hello"))  # False
print(is_number("-36"))    # True

In the regular expression '^[+-]?\d+$':

^: Asserts the start of the string. The ^ indicates the start of the string.

[+-]?: Matches an optional plus (+) or minus (-) sign. The ? makes the preceding character class [+-] optional.

\d+: Matches one or more digits. \d represents any digits (0-9), and the + quantifier means “one or more”.

$: Asserts the end of the string. The $ indicates the end of the string.

This pattern checks for an optional sign at the beginning and one or more digits, ensuring the entire string is a valid integer.

Handling decimal point numbers (float)

Below is a code example that checks if a string is a number with an optional sign and decimal point.

import re


def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Define a regular expression pattern 
    pattern = re.compile(r'^[+-]?\d+(\.\d+)?$')

    # Return True if the pattern matches the entire string
    return bool(pattern.match(str))


print(is_number("22"))     # True
print(is_number("-36"))    # True
print(is_number("3.14"))   # True
print(is_number("2."))     # False
print(is_number(".9"))     # False

In the regular expression '^[+-]?\d+(\.\d+)?$':

^: Asserts the start of the string. The ^ indicates the start of the string.

[+-]?: Matches an optional plus (+) or minus (-) sign. The ? makes the preceding character class [+-] optional.

\d+: Matches one or more digits. \d represents any digits (0-9), and the + quantifier means “one or more”.

 (\.\d+)?: This part makes an optional decimal point followed by one or more digits.

  • ( and ): Parentheses create a capturing group for the decimal part. This allows you to group parts of the regular expression and apply quantifiers to them.
  • \.: The backslash \ is an escape character. It escapes the dot, making it match a literal dot (decimal point).
  • \d+: Matches one or more digits after the decimal point.
  • ?: The ? makes the entire capturing group optional.

$: Asserts the end of the string. The $ indicates the end of the string.

Handling scientific notation numbers

Below is a code example that checks if a string is a number (integer, float, or scientific notation number):

import re


def is_number(str):
    # Remove leading and trailing whitespace
    str = str.strip()

    # Define a regular expression pattern for a number (integer, float, or scientific notation)
    pattern = re.compile(r'^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$')

    # Return True if the pattern matches the entire string
    return bool(pattern.match(str))


print(is_number("22"))     # True
print(is_number("3.14"))   # True
print(is_number("3e2"))    # True
print(is_number("5e3"))    # True
print(is_number("9a3"))    # False

In this updated code, the regular expression '^[+-]?\d+(\.\d+)?([eE][+-]?\d+)?$' has been extended to include an optional exponent part:

([eE][+-]?\d+)?: This part allows for an optional exponent part in the form of e or E followed by an optional plus or minus sign and one or more digits.

  • ( and ): Parentheses create a capturing group for the decimal part. This allows you to group parts of the regular expression and apply quantifiers to them.
  • [eE]: Mathes either an 'e' or 'E', representing the exponent part in scientific notation. The square brackets [eE] define a character class that matches either 'e' or 'E'
  • [+-]?: Matches an optional plus (+) or minus (-) sign. The ? makes the preceding character class [+-] optional.
  • \d+: Matches one or more digits. \d represents any digits (0-9), and the + quantifier means “one or more”.
  • ?: The entire capturing group ([eE][+-]?\d+) is followed by a ?, which makes the entire group optional. This means that the exponent part is not required in the pattern. The ? quantifier applies to the entire capturing group, making it optional as a whole.

Putting it all together, ([eE][+-]?\d+)? allows for an optional exponent part in the number, specifically in scientific notation. If present, it consists of an 'e' or 'E', an optional plus or minus sign, and one or more digits. If absent, the entire exponent part is optional.

Conclusion:

In conclusion, selecting the appropriate method for checking if a string is a number in Python depends on your specific requirements.

While the try-except block offers flexibility, it’s generally slower than other methods, especially for non-numeric strings. If speed is crucial, consider isdigit() or isnumeric() methods instead.

For cases where you want to ensure the string consists of only digits (0-9), the isdigit() method is a straightforward choice. While it doesn’t directly handle floats or scientific notation, you can extend its functionality using regular expression or string-splitting techniques to accommodate those number formats.

For broader number recognition across various languages and Unicode characters, the isnumeric() method provides flexibility. However, you cannot extend its functionality to handle scientific notation.

Finally, for more complex scenarios or specific number formats, utilizing regular expression provides a flexible solution.

Consider your project’s demands and choose the right method that best aligns with your objectives. 

Happy Coding !!!—