2

In the below example I create a custom type, then an array of elements of this type and then I test the first element of this array against this type with isinstance(), but I get an Error.

import numpy as np

# Here I define a simple type with two fields
my_type_simple = np.dtype([('field_1', int), ('field_2', float)])
# An array using the above type
my_var_simple_1 = np.array([(1, 1), (2, 2)], dtype=my_type_simple)
# For a check, should print [(1, 1.) (2, 2.)]
print(my_var_simple_1)
# For a check, should print True
print(isinstance(my_var_simple_1, np.ndarray))
# The below prints numpy.void - how can I find out that in fact it is 'my_type_simple' ?
print(type(my_var_simple_1[0]))
# The below prints True, at least
print(isinstance(my_var_simple_1[0], type(my_var_simple_1[0])))
# But the below raises an Error: TypeError: isinstance() arg 2 must be a type or tuple of types
print(isinstance(my_var_simple_1[0], my_type_simple))

Therefore the question is: how can I test to find out that the type of my_var_simple_1[0] is in fact my_simple_type? Is that at all possible?

Maciek
  • 762
  • 6
  • 17

3 Answers3

2

Try that, see if it suits your needs:

my_var_simple_1[0].dtype == my_type_simple
Or Y
  • 2,088
  • 3
  • 16
  • 1
    Damn, that was easy, why did I fix on `isinstance()`? Here the only caveat is that if I deal with a list, it won't have the `dtype` field, but that can be easily worked around. Thank you for your help! – Maciek Sep 22 '20 at 14:31
  • @Maciek. What would you put in a list that's analogous to an instance of a numpy dtype? – Mad Physicist Sep 22 '20 at 20:32
  • @MadPhysicist sorry, I don't understand the question. – Maciek Sep 23 '20 at 07:24
  • @Maciek. You say "Here the only caveat is that if I deal with a ...". What does that mean? How is that relevant? How do you have structured numpy dtypes in a list? The whole question seems very specific to numpy arrays – Mad Physicist Sep 23 '20 at 12:04
  • @MadPhysicist, well, it is just that numpy methods tend to work with ndarrays, but also iterables, such as lists, thus I wanted my methods to be generic too. – Maciek Sep 23 '20 at 12:08
  • @Maciek. Numpy methods don't work work most iterates or even sequences except lists and tuples. They do so by calling `np.array`, `np.asarray`, `np.asanyarray`, or similar on the list. I suggest you do the same. Structured dtypes don't mean anything in a list unless the list already contains arrays. – Mad Physicist Sep 23 '20 at 12:15
  • @Maciek. I recently had a question that's related: https://stackoverflow.com/q/63855789/2988730. Basically, structured dtype scalars are of type `np.void`, which is related to `bytes`. You can't represent then meaningfully without wrapping in an array. – Mad Physicist Sep 23 '20 at 12:18
1
In [7]: my_type_simple = np.dtype([('field_1', int), ('field_2', float)])
   ...: # An array using the above type
   ...: my_var_simple_1 = np.array([(1, 1), (2, 2)], dtype=my_type_simple)

The dtype command creates an dtype object, an instance of that class. It doesn't subclass dtype.

In [8]: type(my_type_simple)
Out[8]: numpy.dtype

The object created with np.array is a numpy array, ndarray. That's true regardless of the dtype.

In [11]: type(my_var_simple_1)
Out[11]: numpy.ndarray

For compound dtypes the type of an element is void. The type for each of your two fields is np.int64 and np.float64, but the combination is np.void.

In [12]: type(my_var_simple_1[0])
Out[12]: numpy.void

But we can access the dtype of the array or its element, and test that:

In [13]: my_var_simple_1.dtype
Out[13]: dtype([('field_1', '<i8'), ('field_2', '<f8')])
In [16]: my_var_simple_1[0].dtype
Out[16]: dtype([('field_1', '<i8'), ('field_2', '<f8')])

While type or isinstance can be useful in checking whether an object is ndarray as opposed to list or something else, the dtype is more useful when checking the properties of the array itself. (asking for alist.dtype will raise an error, since lists don't have such an attribute.) (Object dtype arrays are more like lists.)

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thanks, in fact I realized all these I think. The fact that the structured type is `np.void` disallowed me to test various types. I could print to screen `dtype([('field_1', ' – Maciek Sep 23 '20 at 07:27
0

You are creating a custom numpy dtype. isinstance does not apply to the contents of an ndarray. For more info read this. For your problem you can do:

type(my_var_simple_1[0].item())

or like Or Y mentioned:

my_var_simple_1[0].dtype
Diogo Silva
  • 320
  • 2
  • 14
  • Yeah, this I already thought about, but would need to specially create a data element just to perform testing. Thanks for the link, I did not find that question when looking for relevant discussion earlier on. – Maciek Sep 22 '20 at 14:33