Functionality for working with different strides `memoryview`s

In issue ( Can't read a F-contiguous memoryview in physical order · Issue #80026 · python/cpython · GitHub ), ( Memoryview for column-major (f_contiguous) arrays from bytes impossible to achieve · Issue #78959 · python/cpython · GitHub ), and issue ( Supporting `strides` in `memoryview.cast` · Issue #85398 · python/cpython · GitHub ), it is brought up that handling striding other that C-contiguous (like F-contiguous) is kind of tricky with memoryview. There are a few ways one might go about improving on this:

  1. Allow users to override strides (say in memoryview.cast(...))
  2. Provide an order flag for operations (like memoryview.cast(...))
  3. Add a .T attribute to memoryview to allow transposing (reversing memoryview.strides)
  4. Add .transpose(...) to memoryview to allow specifying the new axis order

There is probably some value for any of these changes. Several array libraries implement things like these.

Personally would argue manipulating strides directly while quite powerful is often more difficult for people to understand. Similarly .transpose(...) provides a lot of flexibility and is a bit easier to understand, it often dovetails well with other operations a fully fledged array library might provide.

This leaves (2) adding an order parameter to .cast(...) and (3) adding .T attribute. Both would be fine and are fairly easy to understand. Though if we had to choose, would lean towards .T as it can already be combined easily with normal .cast(...) operations and can be valuable on its own (moving from F-contiguous to C-contiguous for example). Also .T should be fairly simple to implement (copy the memoryview data as in .cast(...) and reverse the strides).

Would be curious to hear others thoughts on these and any other proposals one might have. Also curious about your preferences as well. Thanks for your feedback! :smile:

Those memoryview issues predate the array API, which is a standard set by a consortium of array API library stakeholders.

The standard has a clear position about the .mT attribute but does not set forth semantics of cast. The discussion in issue 80026 I think refers to adding a kwarg to tobytes (also not part of the API standard) rather than changing cast. Would this solve the problem you are addressing?

copy the memoryview data as in .cast(...)

Does cast create a new data copy or does it provide a new view into the currently allocated data? I think the latter:

a = np.empty([2, 2])
m1 = memoryview(a)
m1.obj is a  #True
m2 = m1.cast('b')
m2.obj is a  # True

The array API does discuss the idea of views vs. copy, and leaves the decision up to the library author.

I am curious what your use case for any of this is. It would be good to have some actual code usage to drive the discussion about which alternative would best help users. Personally, I would like to see cython’s pure-python mode move towards recommending memoryview buffers rather than using NumPy ndarrays, which might require a full-blown interface to manipulating strides. Although that is pure speculation on my part, and not due to an investigation of what would actrually be required.