10

In Python, how could you check if the type of a number is an integer without checking each integer type, i.e., 'int', 'numpy.int32', or 'numpy.int64'?

I thought to try if int(val) == val but this does not work when a float is set to an integer value (not type).

In [1]: vals = [3, np.ones(1, dtype=np.int32)[0], np.zeros(1, dtype=np.int64)[0], np.ones(1)[0]]
In [2]: for val in vals:
   ...:     print(type(val))
   ...:     if int(val) == val: 
   ...:         print('{} is an int'.format(val))
<class 'int'>
3 is an int
<class 'numpy.int32'>
1 is an int
<class 'numpy.int64'>
0 is an int
<class 'numpy.float64'>
1.0 is an int

I want to filter out the last value, which is a numpy.float64.

Steven C. Howell
  • 16,902
  • 15
  • 72
  • 97
  • If it is an array (or `np` datatype) you check the `dtype`. See http://stackoverflow.com/questions/40312013/check-type-within-numpy-array. As note there, `arr[0].item()` will extract the item to a Python numeric type. – hpaulj Nov 04 '16 at 18:54
  • @hpaulj, I am considering only a single value, not an array. I used a list to demonstrate in this example. – Steven C. Howell Nov 04 '16 at 18:57
  • The single value still has `numpy` wrapper. Use `item()` to remove that. – hpaulj Nov 04 '16 at 18:58
  • @hpaulj, `item()` work with numpy objects but crashes if the number is already a Python numeric type. It could be used in a `try: except:` clause, but not a one line `if` statement. – Steven C. Howell Nov 04 '16 at 19:01
  • Look at the `np.float64.__mro__` (and same for other `dtypes`). Since `float` is in that list `isinstance(np.float64(2), float)` returns `True`. – hpaulj Nov 04 '16 at 20:42

5 Answers5

23

You can use isinstance with a tuple argument containing the types of interest.

To capture all python and numpy integer types use:

isinstance(value, (int, np.integer))



Here is an example showing the results for several data types:

vals = [3, np.int32(2), np.int64(1), np.float64(0)]
[(e, type(e), isinstance(e, (int, np.integer))) for e in vals]

Result:

[(3, <type 'int'>, True), 
 (2, <type 'numpy.int32'>, True), 
 (1, <type 'numpy.int64'>, True), 
 (0.0, <type 'numpy.float64'>, False)]


A second example which is true only for int and int64:

[(e, type(e), isinstance(e, (int, np.int64))) for e in vals]

Result:

[(3, <type 'int'>, True), 
(1, <type 'numpy.int32'>, False), 
(0, <type 'numpy.int64'>, True), 
(0.0, <type 'numpy.float64'>, False)]
amicitas
  • 13,053
  • 5
  • 38
  • 50
dawg
  • 98,345
  • 23
  • 131
  • 206
9

In addition to the accepted answer, the standard library also provides the numbers module, which defines abstract classes for numerical types that can be used with isinstance:

isinstance(value, numbers.Integral)

This can be used to recognize both Python's int as well as NumPy's np.int64.

4

Use np.issubdtype:

for val in vals:
    if isinstance(val, int) or np.issubdtype(val, np.int):
        print('{} is an int'.format(val))
Francisco
  • 10,918
  • 6
  • 34
  • 45
3

The simplest solution appears to be:

isinstance(value, (int, np.integer))
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
0

You can also use duck typing:

hasattr(val, "denominator") and val.denominator == 1
Marco Sulla
  • 15,299
  • 14
  • 65
  • 100