When I run these methods
s.isdigit()
s.isnumeric()
s.isdecimal()
I always got as output or all True, or all False for each value of s (whic
The Python documentation notes the difference between the three methods.
Return true if all characters in the string are digits and there is at least one character, false otherwise. Digits include decimal characters and digits that need special handling, such as the compatibility superscript digits. This covers digits which cannot be used to form numbers in base 10, like the Kharosthi numbers. Formally, a digit is a character that has the property value Numeric_Type=Digit or Numeric_Type=Decimal.
Return true if all characters in the string are numeric characters, and there is at least one character, false otherwise. Numeric characters include digit characters, and all characters that have the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric characters are those with the property value Numeric_Type=Digit, Numeric_Type=Decimal or Numeric_Type=Numeric.
Return true if all characters in the string are decimal characters and there is at least one character, false otherwise. Decimal characters are those that can be used to form numbers in base 10, e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in the Unicode General Category “Nd”.
Like @Wim said, the main difference between the three methods is the way they handle specific unicode characters.
a negative number a = "-10"
would be false for all of these three
a.isdecimal(), a.isdigit(), a.isnumeric()
are False, False, False isdecimal() will have only 0 to 9 in any language, but with out negative signs isdigit() will have only 0 to 9 in any language, also in the "to the power of" positions. (decimal numbers in power, ex: 2 to the power of 5). isnumeric() is even broader spectrum.. it will also include more than 0 to 9 in any position, but it will also have Tens, hundred, thousands in any language, ex. roman 10 is X, its a valid isnumeric(). But all the three are false for: Negative numbers, ex: -10 and floating point numbers, ex: 10.1
By definition, isdecimal()
⊆ isdigit()
⊆ isnumeric()
. That is, if a string is decimal
, then it'll also be digit
and numeric
.
Therefore, given a string s
and test it with those three methods, there'll only be 4 types of results.
+-------------+-----------+-------------+----------------------------------+
| isdecimal() | isdigit() | isnumeric() | Example |
+-------------+-----------+-------------+----------------------------------+
| True | True | True | "038", "੦੩੮", "038" |
| False | True | True | "⁰³⁸", "
It's mostly about unicode classifications. Here's some examples to show discrepancies:
>>> def spam(s):
... for attr in 'isnumeric', 'isdecimal', 'isdigit':
... print(attr, getattr(s, attr)())
...
>>> spam('½')
isnumeric True
isdecimal False
isdigit False
>>> spam('³')
isnumeric True
isdecimal False
isdigit True
Specific behaviour is in the official docs here.
Script to find all of them:
import sys
import unicodedata
from collections import defaultdict
d = defaultdict(list)
for i in range(sys.maxunicode + 1):
s = chr(i)
t = s.isnumeric(), s.isdecimal(), s.isdigit()
if len(set(t)) == 2:
try:
name = unicodedata.name(s)
except ValueError:
name = f'codepoint{i}'
print(s, name)
d[t].append(s)
Related question: which one is equivalent "\d" in regular expression?
"\d": For Unicode (str) patterns: Matches any Unicode decimal digit (that is, any character in Unicode character category [Nd]). This includes [0-9], and also many other digit characters. If the ASCII flag is used only [0-9] is matched.