Python String isdigit: How It Works and When to Use It
python string isdigit: Learn how Python's str.isdigit() works, its Unicode behavior, differences from isnumeric() and isdecimal(), and practical validation use cases.
The python string isdigit method is a built-in string method that returns True if all characters in the string are digits and there is at least one character, otherwise False. It's a common tool for validating user input, but its behavior is more nuanced than many developers expect, especially when Unicode characters are involved.
How str.isdigit() Determines Digit Characters
The method checks each character in the string against the Unicode digit category. A character is considered a digit if it has the Unicode property Numeric_Type=Digit or Numeric_Type=Decimal. This includes the ASCII digits 0 through 9, as well as superscript digits like ² and ³, and digits from other scripts such as Arabic-Indic digits. However, it does not include characters that represent numbers in other ways, like fractions or Roman numerals.
print("123".isdigit()) # True print("12.3".isdigit()) # False (contains a decimal point) print("²³".isdigit()) # True (superscript digits) print("١٢٣".isdigit()) # True (Arabic-Indic digits)
Notice that "²³".isdigit() returns True because superscript two and three are classified as digits. This is often surprising to developers who expect isdigit() to only recognize ASCII digits.
Basic Usage and Return Behavior
The method takes no arguments and returns a boolean. It is case-sensitive in the sense that letters are never digits, so "A1".isdigit() is False. The method also requires at least one character; an empty string returns False.
print("".isdigit()) # False print("0".isdigit()) # True print(" 1".isdigit()) # False (space is not a digit) print("12345".isdigit()) # True
The check is all-or-nothing: every single character must satisfy the digit property. If any character fails, the entire string is rejected. This makes isdigit() a strict validator for strings that should contain only digits.
Unicode Digits and Non-ASCII Characters
Python strings are sequences of Unicode code points, and isdigit() follows the Unicode standard. This means that many characters you might not think of as digits are included. For example, the Devanagari digit ४ (U+096A) is a digit, so "४".isdigit() returns True. Similarly, the fullwidth digit 1 (U+FF11) is also a digit.
However, some characters that represent numbers are not digits. For instance, the fraction ½ (U+00BD) has a numeric value but is not a digit, so "½".isdigit() returns False. The same applies to circled numbers like ① (U+2460) and Roman numerals.
This distinction is critical when your application needs to handle international input. If you only want to accept ASCII digits, you need to filter explicitly:
def is_ascii_digit_string(s): return s.isdigit() and all(ord(c) < 128 for c in s)
Or use a regular expression like ^[0-9]+$.
Comparing isdigit(), isnumeric(), and isdecimal()
Python provides three related methods: str.isdecimal(), str.isdigit(), and str.isnumeric(). They differ in the set of characters they accept. The table below summarizes the hierarchy:
| Method | Accepts decimal digits (0-9, Arabic-Indic) | Accepts superscripts, subscripts, and other digit-like characters | Accepts fractions, Roman numerals, and other numeric characters |
|---|---|---|---|
isdecimal() | Yes | No | No |
isdigit() | Yes | Yes | No |
isnumeric() | Yes | Yes | Yes |
For most validation tasks where you expect ordinary decimal numbers, isdecimal() is the safest choice. It rejects superscripts and other exotic digit forms. isdigit() is a middle ground, and isnumeric() is the most permissive.
print("²".isdecimal()) # False print("²".isdigit()) # True print("²".isnumeric()) # True print("½".isdecimal()) # False print("½".isdigit()) # False print("½".isnumeric()) # True
If your application processes financial data or user-entered numbers, using isdecimal() prevents accidental acceptance of superscript digits that might cause bugs downstream.
Common Pitfalls with Empty Strings and Whitespace
A frequent mistake is assuming isdigit() returns True for an empty string. It does not. You must check the length separately if an empty string is invalid in your context.
Another pitfall is forgetting that whitespace is not a digit. A string like " 123" or "123 " will return False. If you need to allow leading or trailing spaces, you should strip the string first:
user_input = " 123 " if user_input.strip().isdigit(): print("Valid number")
Also, negative numbers and decimal points are not digits. "-123".isdigit() is False, and "3.14".isdigit() is False. If you need to validate numeric strings that may include signs or decimal points, isdigit() is not sufficient. You should use a parsing function like float() inside a try block or a regular expression.
Using isdigit() for Input Validation
A common use case is validating that a string contains only digits before converting it to an integer. For example, when reading a port number or a quantity from a form:
quantity = input("Enter quantity: ") if quantity.isdigit(): n = int(quantity) print(f"You entered {n}") else: print("Invalid quantity")
This works well for non-negative integers. However, note that isdigit() accepts Unicode digits, so int("١٢٣") will work because Python's int() can parse Arabic-Indic digits. If you want to restrict to ASCII digits, use the explicit check shown earlier.
Another practical pattern is checking that a string represents a valid integer in a specific base. isdigit() does not care about base; it only checks characters. For base 16, you'd need to allow A-F, so this method is not appropriate.
Performance and Maintainability Considerations
isdigit() is implemented in C and is highly optimized. For typical string lengths, it is faster than a regular expression or a manual loop. If you are validating many short strings, isdigit() is a good choice. However, if you need to handle signs, decimals, or other numeric formats, a regular expression might be more maintainable even if slightly slower.
When used in a loop over large datasets, the method's performance is predictable because it scans the string once. There is no hidden memory allocation beyond the boolean result. For very long strings, the time is proportional to the length, but that is rarely a bottleneck.
From a maintainability perspective, isdigit() is clear and self-documenting. The intent is obvious to any Python developer. If you need more complex validation, consider writing a small helper function that uses isdigit() as a building block, rather than embedding regex patterns throughout your code.
def is_positive_int_str(s): return s.isdigit() and len(s) > 0
This keeps the validation logic centralized and avoids repetition.
Choosing the Right Method for Your Data
Selecting between isdecimal(), isdigit(), and isnumeric() depends on the domain of your data. If you are building a system that accepts international phone numbers or quantities, you might want to allow Unicode digits. If you are parsing configuration files that must be ASCII, you need a stricter check.
The key is to understand the Unicode classification and test with representative inputs. A quick way to see which characters pass is to use a small script:
for ch in "0123456789²½١": print(ch, ch.isdecimal(), ch.isdigit(), ch.isnumeric())
Running this will show the differences clearly. Always consider the full range of input your application might receive, especially if it is user-facing.
For most modern web applications, using isdecimal() is a safer default because it avoids surprising superscripts and other edge cases. If you need to match exactly what a user would type as a digit, isdecimal() is the closest to the common interpretation.
Remember that isdigit() is not a substitute for parsing. It only checks the character set, not the numeric value or range. For example, "999999999999999999999999999999".isdigit() returns True, but converting it to an integer might raise OverflowError on some platforms if it exceeds the maximum integer size. In Python 3, integers are arbitrary precision, so this is less of a concern, but it is still worth noting.
When you need to validate a string that represents a number with a sign or decimal, use a try/except with float() or Decimal instead of relying on isdigit(). The method is intentionally narrow and should be used only for digit-only strings.