I'm no numpy expert, so I might be a bit off here, but here's my understanding.
We define a structured data type with two named fields, 'a' and 'b'. Both of these fields contain a little-endian (<) integer (i) of 32 bits (4 bytes).
This is the data type associated with the array we're storing. So every element in our custom datatype takes its first field ('a') from the first element in our array (x[0]), and the second element ('b') from the second element in our array (x[1]).
If we look at all the values of the first field, x['a'] we get an array - [1,3].
If we look at all the values of the second field, x['b'] we get another array, that of the values in the second element - [2,4].
We can have our array store 3 elements but would have to maintain the 2-field structure.
x = np.array([(1,2), (3,4), (5,6)], dtype=[('a','<i4'), ('b','<i4')])
>>> x['a']
array([1, 3, 5], dtype=int32)