bitcreed

Linux & Systems

Python isnumeric() and isdigit() on Unexpected Characters

· updated

Some unexpected characters are numeric or digits. I found a trait of str.isnumeric() and str.isdigit() that I didn’t expect.

What the help texts say

Let’s first look at the help texts (Python 3.10.6). isdigit(self, /):

Return True if the string is a digit string, False otherwise.

A string is a digit string if all characters in the string are digits and there
is at least one character in the string.

And conversely, isnumeric(self, /):

Return True if the string is a numeric string, False otherwise.

A string is numeric if all characters in the string are numeric and there
is at least one character in the string.

This gives the impression that a string consisting only of digits must be a number, and in most cases this works as expected:

>>> num_str = "1234"
>>> num_str.isdigit()
True
>>> num_str.isnumeric()
True
>>> int(num_str)
1234

Superscripts and fractions

But then there are superscript numbers and fraction characters, which I didn’t expect and which you should consider:

>>> pow3 = '³'
>>> pow3.isdigit()
True
>>> pow3.isnumeric()
True
>>> int(pow3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '³'

>>> quarter = '¼'
>>> quarter.isdigit()
False
>>> quarter.isnumeric()
True
>>> float(quarter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: '¼'

Validate with a regular expression

So consider using good old (and slower) regular expressions to validate input that is then fed to int() or float():

import re

re.match('\d+', pow3)  # this pretend-digit is no match for regex :D