-1

I am running in this multiple times now and never found a satisfying solution.

I want to check: Is variable some_var of a number type?
More specific for me: Can it be compared to another number? (e.g. a string should fail)

Numpy makes this somehow difficult since:

some_var = np.int32(123)
isinstance(some_var, int)
>>> False

Possible Solutions

numpy solutions: np.issubtype, comparison to np.number, np.isscalar

I found np.issubtype as workaround, but this will fail for non-numpy types:

some_var = 123
np.issubdtype(some_var.dtype, np.number)
>>> AttributeError: 'int' object has no attribute 'dtype'

np.number can be used for comparison, but also fails for non-numpy types

isinstance(1, np.number)
>>> False

np.isscalar() works fine, but also allows strings:

np.isscalar('test')
>>>True

numbers module

There is the comparison with the numbers module. Which seems to work convenient, but needs an extra import. So far probably the best solution.

from numbers import Integral

isinstance(some_var, Integral)
>>> True

Manual testing

The clearest way of course would be a manual test.

isinstance(some_var, (int, float, np.int32, np.int64, np.float32, np.float64))
>>> True

My Questions

Am I missing a way?
What would be the most recommended?

CodePrinz
  • 445
  • 5
  • 8
  • 1
    You can use `np.issubdtype(some_var, np.number)`.. – ko3 Jul 14 '22 at 09:43
  • Have a look at https://stackoverflow.com/questions/4138202/using-isdigit-for-floats, I think the first answer is what you need – Giovanni Tardini Jul 14 '22 at 12:19
  • 2
    Does `'12.3'` count as number or string? – hpaulj Jul 14 '22 at 14:12
  • `isinstance(some_var, np.number)` works too. As long at is dtype a number and not a string that contains the representation of a number as hpaulj implies. – Scott Boston Jul 14 '22 at 15:42
  • Thanks for the input. I updated the question that in my case `'12.3'` (strings) should not count and added the `isinstance(...,np.number)` solution, which sadly won't work for int and float. – CodePrinz Jul 15 '22 at 12:29

1 Answers1

1

As the short answer did not catch the audience, here the extended answer: There is no generic function to check against every numeric type in existance, as every package can implement their own.

It is also advisable, to control, which variable types to accept, as packages can have different implementation behaviour (e.g. integer division 1 / 10 = 0.1 or 1 / 10 = 0.

Therefore a simple isNumeric check is advisable.

Now two versions come to my mind:

NUMERIC_TYPES = [int, float, ...] #to be extended by acceptable types
def isNumeric(val):
    return isinstance(val, NUMERIC_TYPES)

however there is a more performant version (my laptop 15%)

NUMERIC_TYPES = set((int, float, np.int32, np.int64, np.float32, np.float64,...))

def isNumeric(val):
    return type(val) in NUMERIC_TYPES

And for @CodePrinz isinstance and type(x)== is not the same!

class StupidInt(int):
    def __init__(self, val):
        self._privateInt = val
    def __add__(self, other):
        return self._privateInt - other

a = StupidInt(10)
b = StupidInt(10)
print("a + b = 0? whaaat?")
print(a+b)

print("isInstance: {}".format(isinstance(a, int)))
print("is of type: {}".format(type(a) == int))
----
a + b = 0? whaaat?
0
isInstance: True
is of type: False
FloLie
  • 1,820
  • 1
  • 7
  • 19
  • This will not work for numpy types as np.int32. – CodePrinz Jul 14 '22 at 11:12
  • and `isinstance(val, (int, float))` does the same and is more obvious. – CodePrinz Jul 14 '22 at 11:20
  • 1
    well obviously, the numericTypes is supposed to be extended to the full set of accepted data types. And also it is nicer to abstract it to a function, that does express the purpose (and is shorter than repeating ```ìsinstance(....)```. And third, isInstance at least in the past does have a reputation for being slow. A lookup against a set is ```O(1)``` quiet efficient – FloLie Jul 14 '22 at 15:08
  • @CodePrinz please look at the update. there are definitly reasons not to use isinstance. – FloLie Jul 14 '22 at 15:36
  • Thanks for the more elaborated answer! In my case I think every child of an allowed class would be good to go. I was taught to prefer of-the-shelf solutions to selft-written functions. Of course often such a replacement can make sense. – CodePrinz Jul 15 '22 at 12:41