Search code examples
pythonnumpystride

How do I get the strides from a dtype in numpy?


I think I can do: np.zeros((), dtype=dt).strides, but this doesn't seem efficient when the dtype is a large array type like: ('<f8', (200, 100)). Is there a way of going directly from dtype to strides in numpy?


Solution

  • You can actually get the strides of a sub-array within a structured array without creating the "full" array.

    Sub-arrays within a structured array are required to be contiguous and in C-order according to the documentation. Note the sentence just above the first example:

    Sub-arrays always have a C-contiguous memory layout.

    Therefore, for a structured array with no fields such as the one in your example, you can do (as an unreadable one-liner):

    import numpy as np
    
    x = np.dtype(('<f8', (200, 100)))
    
    strides = x.base.itemsize * np.r_[1, np.cumprod(x.shape[::-1][:-1])][::-1]
    

    Avoiding the code golf:

    shape = list(x.shape)
    
    # First, let's make the strides for an array with an itemsize of 1 in C-order
    tmp_strides = shape[::-1]
    tmp_strides[1:] = list(np.cumprod(tmp_strides[:-1]))
    tmp_strides[0] = 1
    
    # Now adjust it for the real itemsize:
    tmp_strides = x.base.itemsize * np.array(tmp_strides)
    
    # And convert it to a tuple, reversing it back for proper C-order
    strides = tuple(tmp_strides[::-1])
    

    This gets more complex when there are multiple fields, however. You'd need to put in approriate checks in general. For example: Does the dtype have a shape attribute? Does it have fields? Do any fields have shape attributes?