Package: is-numeric
is-numericReally simple.  A method to test if a valueis_numeric.fromis_numericimportis_numericprint(is_numeric(1))# Trueprint(is_numeric(-1))# Trueprint(is_numeric(123))# Trueprint(is_numeric(123.456))# Trueprint(is_numeric("123.456"))# Trueprint(is_numeric("x"))# Falseprint(is_numeric("1x"))# FalseInstallationpip install is-numericNotes on the algorithmI tested 4 algorithms:str.isinstanceerror-drivenregexregex (plus str.isinstance)str.isinstanceUsing the built in .isinstance is limited in functionality, as it only looks for all characters being a digit, and fails on '-1' or '1.2'.  Thus discard this approach.def _str_isnumeric(value):
    if isinstance(value, (int, float)):
        return True
    if isinstance(value, str) and value.isnumeric():
        return True
    return Falseerror-drivenThis is ugly in that it relies on errors in flow control.  I hate it.  It is like nails on chalk board to me.def _is_numeric_using_error(value):
    try:
        float(value)
        return True
    except ValueError:
        return FalseregexThis seems elegant.  Check for a pattern.def _is_numeric_regex(value):
    if isinstance(value, (int, float)):
        return True
    if isinstance(value, str):
        return bool(re.match(r"^-?\d+(\.\d+)?$", value))
    return Falseregex (plus str.isinstance)The regex solution, with a small change to check if all numeric digits prior to doing regex.def _is_numeric_regex_plus_isnumeric(value):
    if isinstance(value, (int, float)):
        return True
    if isinstance(value, str) and value.isnumeric():
        return True
    if isinstance(value, str):
        return bool(re.match(r"^-?\d+(\.\d+)?$", value))
    return FalsePerformance ComparisonI ran a very non-scientific test.ApproachCreate a list of inputs, with a mix of float/int, strings that represent numeric values, and non-numeric values.
Iterate x time over the list for a given algorithm.
Repeat for each algorithm.Variable% of inputs that are non-numeric (theory is that error-driven will perform better when the value is numeric, and less efficient when the value cannot be cast to float and an error is raised)FindingsWhen most values are numeric [^1] (0-50%), the error-driven approach outperforms other approaches (up to 3x).When most values are non-numeric [^2] (80%), the regex (plus str.isinstance) approach has a very slight advantage (4%).Conclusionwithout knowning the % of non-numeric values, it is recommended to use the error-driven approach.  As such, the error-drive approach is exposed through theis_numericfunction in this package.Raw Dataconst: iterations=1000000Algorithm% Non-NumericTime in SecondsIterations per Secondis_numeric_regex_plus_isnumeric0.04.176071239,459.52is_numeric_using_error0.01.469144680,668.39is_numeric_regex0.04.719131211,903.44is_numeric_regex_plus_isnumeric0.25.893955169,665.37is_numeric_using_error0.23.295613303,433.65is_numeric_regex0.26.379531156,751.32is_numeric_regex_plus_isnumeric0.510.68753893,566.92is_numeric_using_error0.58.338870119,920.32is_numeric_regex0.510.84800092,182.89is_numeric_regex_plus_isnumeric0.829.75048833,612.89is_numeric_using_error0.828.50890635,076.76is_numeric_regex0.828.43933435,162.57[^1]: numeric = float/int, strings that represent numeric values
[^2]: non-numeric = strings that cannot be cast to float/int