memoryview is one of the built-in types and can simply be called as:

arr = np.random.rand(5,4)
view = memoryview(arr)
view
<memory at 0x12699c318>
Answer from Grr on Stack Overflow
🌐
Cython
cython.readthedocs.io › en › latest › src › userguide › memoryviews.html
Typed Memoryviews — Cython 3.3.0 documentation
Of course, you are not restricted to using NumPy’s type (such as cnp.int32_t here), you can use any usable type. Although memoryview slices are not objects they can be set to None and they can be checked for being None as well:
Discussions

python - Cython: Convert memory view to NumPy array - Stack Overflow
How to convert a typed memoryview to an NumPy array in cython? The docs have cimport numpy as np import numpy as np numpy_array = np.asarray( my_pointer) I took this f... More on stackoverflow.com
🌐 stackoverflow.com
Allow numpy to copy internal buffer into memoryview
Hello, I have a C extension which maps memory address to a pointer. In this extension, I return this pointer through a memoryview PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags). In my python code, I created a numpy array ... More on github.com
🌐 github.com
4
December 21, 2016
Assembling a cython memoryview from numpy arrays - Stack Overflow
I have a bunch of numpy arrays as attributes of an array of python objects, in cython, in preparation for prange processing (which requires nogil), I wanted to create a memory view that was "indire... More on stackoverflow.com
🌐 stackoverflow.com
October 24, 2019
ndarray does not accept memoryview for buffer= under python2
I've discovered that ndarray(buffer=memoryview) fails on python 2: In [1]: sys.version Out[1]: '2.7.10 (default, May 26 2015, 13:16:40) \n[GCC 4.9.2]' In [2]: numpy.__version__ Out[2]: '1.10.0.dev0+9e7a0b2' In [3]: b = bytearray([1,2,3]) In [4]: b Out[4]: bytearray(b'\x01\x02\x03') In [5]: ... More on github.com
🌐 github.com
4
June 2, 2015
🌐
Python Data Science Handbook
jakevdp.github.io › blog › 2012 › 08 › 08 › memoryview-benchmarks
Memoryview Benchmarks | Pythonic Perambulations
The only change is that instead of using the np.ndarray[...] type specifier, we use the typed memoryview double[:, ::1] specifier. The ::1 in the second position means that we are passing a two-dimensional array, which is contiguous and C-ordered. We time the results and see the following: In [1]: import numpy as np In [2]: from memview_bench_v3 import pairwise In [3]: X = np.random.random((500, 3)) In [4]: timeit pairwise(X) 10 loops, best of 3: 22 ms per loop
🌐
w3resource
w3resource.com › python-exercises › extended-data-types › python-extended-data-types-index-memory-views-exercise-3.php
NumPy memory views in Python: 1D and 3D array examples
August 11, 2025 - import numpy as np def main(): try: # Create a NumPy array array_1_d = np.array([1, 2, 3, 4, 5, 6]) array_3_d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) # Create memory views from the NumPy arrays print("Memory views:") mem_view_1_d = memoryview(array_1_d) print(mem_view_1_d) mem_view_3_d = memoryview(array_3_d) print(mem_view_3_d) # Print the memory views print("\n1-D Memory View:") print(mem_view_1_d.tolist()) print("\n3-D Memory View:") print(mem_view_3_d.tolist()) except Exception as e: print("An error occurred:", e) if __name__ == "__main__": main() Output: Memory views: <memory at 0x00000266DBB4E108> <memory at 0x00000266DBB085E8> 1-D Memory View: [1, 2, 3, 4, 5, 6] 3-D Memory View: [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]] The above exercise demonstrates how to create memory views from NumPy arrays and print their contents.
🌐
Python⇒Speed
pythonspeed.com › articles › numpy-memory-views
NumPy views: saving memory, leaking memory, and subtle bugs
January 6, 2023 - NumPy has a built-in feature that does this transparently, in many common cases: memory views. However, this feature can also cause higher memory usage by preventing arrays from being garbage collected.
🌐
Google Groups
groups.google.com › g › cython-users › c › AYFMrvSTVr4
creating a memoryview from scratch
If I use regular old malloc, and copy to the memoryview, then how/when do I free that memory? Memory will be released, when the view.array is destroyed. A numpy array created with asarray will share memory and keeps a reference, so memory keeps allocated as long the numpy array exists.
Find elsewhere
🌐
Codecademy
codecademy.com › docs › python › built-in functions › memoryview()
Python | Built-in Functions | memoryview() | Codecademy
August 26, 2023 - Note: memoryview() can only be used on objects that support the buffer protocol and have a readable or writable buffer interface, such as byte, bytearray, array.array, numpy arrays, and other objects created using the struct module.
🌐
Simonwenkel
simonwenkel.com › notes › programming_languages › python › cython-memory-views-of-numpy-arrays.html
Cython Memory Views of NumPy Arrays - SimonWenkel.com
October 4, 2020 - The setup is straight forward. The following functions are evaluated on numpy arrays of dimensions (1x1), (10x10), (100x100). On larger arrays (1000x1000, 10000x10000) only numba and cython memory functions were evaluated.
🌐
Cython
cython.readthedocs.io › en › 0.29.x › src › userguide › memoryviews.html
Typed Memoryviews — Cython 0.29.37 documentation
Of course, you are not restricted to using NumPy’s type (such as np.int32_t here), you can use any usable type. Although memoryview slices are not objects they can be set to None and they can be checked for being None as well:
🌐
GitHub
github.com › numpy › numpy › issues › 8408
Allow numpy to copy internal buffer into memoryview · Issue #8408 · numpy/numpy
December 21, 2016 - mymemoryview = MyMemoryView() # pointer on a 24 bytes buffer vertices = np.array([0, -0.5, 0.5, 0.5, -0.5, 0.5], dtype=np.float32) wrapper = np.array(mymemoryview, copy=False, dtype=vertices.dtype) # Wrap my memoryview into a numpy array without copy np.copyto(wrapper, vertices, casting='no')
Author: numpy
Top answer
1 of 1
5

With the below code, you would use this assignment:

cimport stackoverflow_contrib

cdef double[::cython.view.indirect, ::1] vectors =
    stackoverflow_contrib.OnceIndirect([object.vector for object in objects])

where stackoverflow_contrib.pyx is as follows:

from libc.stdlib cimport malloc, free
from libc.string cimport strcmp

from cython.view cimport memoryview
from cpython cimport buffer

cdef class OnceIndirect:
    cdef object _objects
    cdef void** buf
    cdef int ndim
    cdef int n_rows
    cdef int buf_len
    cdef Py_ssize_t* shape
    cdef Py_ssize_t* strides
    cdef Py_ssize_t* suboffsets
    cdef Py_ssize_t itemsize
    cdef bytes format
    cdef int is_readonly

    def __cinit__(self, object rows, want_writable=True, want_format=True, allow_indirect=False):
        """
        Set want_writable to False if you don't want writable data. (This may
        prevent copies.)
        Set want_format to False if your input doesn't support PyBUF_FORMAT (unlikely)
        Set allow_indirect to True if you are ok with the memoryview being indirect
        in dimensions other than the first. (This may prevent copies.)
        """
        demand = buffer.PyBUF_INDIRECT if allow_indirect else buffer.PyBUF_STRIDES
        if want_writable:
            demand |= buffer.PyBUF_WRITABLE
        if want_format:
            demand |= buffer.PyBUF_FORMAT
        self._objects = [memoryview(row, demand) for row in rows]
        self.n_rows = len(self._objects)
        self.buf_len = sizeof(void*) * self.n_rows
        self.buf = <void**>malloc(self.buf_len)
        self.ndim = 1 + self._objects[0].ndim
        self.shape = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)
        self.strides = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)
        self.suboffsets = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)

        cdef memoryview example_obj = self._objects[0]
        self.itemsize = example_obj.itemsize

        if want_format:
            self.format = example_obj.view.format
        else:
            self.format = None
        self.is_readonly |= example_obj.view.readonly

        for dim in range(self.ndim):
            if dim == 0:
                self.shape[dim] = self.n_rows
                self.strides[dim] = sizeof(void*)
                self.suboffsets[dim] = 0
            else:
                self.shape[dim] = example_obj.view.shape[dim - 1]
                self.strides[dim] = example_obj.view.strides[dim - 1]
                if example_obj.view.suboffsets == NULL:
                    self.suboffsets[dim] = -1
                else:
                    self.suboffsets[dim] = example_obj.suboffsets[dim - 1]

        cdef memoryview obj
        cdef int i = 0
        for obj in self._objects:
            assert_similar(example_obj, obj)
            self.buf[i] = obj.view.buf
            i += 1

    def __getbuffer__(self, Py_buffer* buff, int flags):
        if (flags & buffer.PyBUF_INDIRECT) != buffer.PyBUF_INDIRECT:
            raise Exception("don't want to copy data")
        if flags & buffer.PyBUF_WRITABLE and self.is_readonly:
            raise Exception("couldn't provide writable, you should have demanded it earlier")
        if flags & buffer.PyBUF_FORMAT:
            if self.format is None:
                raise Exception("couldn't provide format, you should have demanded it earlier")
            buff.format = self.format
        else:
            buff.format = NULL

        buff.buf = <void*>self.buf
        buff.obj = self
        buff.len = self.buf_len
        buff.readonly = self.is_readonly
        buff.ndim = self.ndim
        buff.shape = self.shape
        buff.strides = self.strides
        buff.suboffsets = self.suboffsets
        buff.itemsize = self.itemsize
        buff.internal = NULL

    def __dealloc__(self):
        free(self.buf)
        free(self.shape)
        free(self.strides)
        free(self.suboffsets)

cdef int assert_similar(memoryview left_, memoryview right_) except -1:
    cdef Py_buffer left = left_.view
    cdef Py_buffer right = right_.view
    assert left.ndim == right.ndim
    cdef int i
    for i in range(left.ndim):
        assert left.shape[i] == right.shape[i], (left_.shape, right_.shape)
        assert left.strides[i] == right.strides[i], (left_.strides, right_.strides)

    if left.suboffsets == NULL:
        assert right.suboffsets == NULL, (left_.suboffsets, right_.suboffsets)
    else:
        for i in range(left.ndim):
            assert left.suboffsets[i] == right.suboffsets[i], (left_.suboffsets, right_.suboffsets)

    if left.format == NULL:
        assert right.format == NULL, (bytes(left.format), bytes(right.format))
    else:
        #alternatively, compare as Python strings:
        #assert bytes(left.format) == bytes(right.format)
        assert strcmp(left.format, right.format) == 0, (bytes(left.format), bytes(right.format))
    return 0

from cython cimport view

cimport numpy as np
import numpy as np

def show_memoryview(object x):
    print dict(shape=x.shape, strides=x.strides, suboffsets=x.suboffsets, itemsize=x.itemsize)

def go():
    row0 = np.array(range(20), dtype=np.float64).reshape(2, 10)
    row1 = np.array(range(20, 40), dtype=np.float64).reshape(2, 10)
    row2 = np.array(range(40, 60), dtype=np.float64).reshape(2, 10)
    small_view = memoryview(row0, buffer.PyBUF_STRIDES)
    show_memoryview(small_view)
    rows = [row0, row1, row2]
        big_view = OnceIndirect(rows)
    cdef double[::view.indirect, :, :] big_view2 = big_view
    cdef int i, j, k
    show_memoryview(big_view2)
    print row1
    big_view2[1, 0, 1] += 200
    print row1
    cdef double[:, :] row1_view = big_view2[1]
    assert row1_view[0, 1] >= 200
    cdef double[::view.indirect, :, :] big_view3 = OnceIndirect([row0, row1, row0])
    cdef double[::view.indirect, ::view.indirect, :, :] dub = OnceIndirect([big_view2, big_view3], allow_indirect=True)
    show_memoryview(dub)
        # big_view2 can be indexed and sliced in Cython and Python code
        # note big_view2 is a cython memoryview object not a OnceIndirect object because it was implicitly cast to one
        # rows, big_view, big_view2 all refer to the same data!
    return (rows, big_view, big_view2)
🌐
Medium
elshad-karimov.medium.com › pythons-memoryview-the-most-underappreciated-python-feature-acde51a8057f
Python’s memoryview – The Most Underappreciated Python Feature! 🚀 | by Elshad Karimov | Medium
February 8, 2025 - This post will unveil the power of memoryview, show how it works, and how you can leverage it for high-performance applications! 🚀 · In Python, when you slice or modify large binary objects (like bytes, bytearrays, or NumPy arrays), a new copy is usually created.
🌐
GeeksforGeeks
geeksforgeeks.org › python › memoryview-in-python
memoryview() in Python - GeeksforGeeks
January 12, 2026 - NumPy · Pandas · Practice · Django · Flask · Last Updated : 12 Jan, 2026 · memoryview() provides direct access to an object’s memory (like bytes, bytearray, or array) without copying it, making operations on large datasets faster and more efficient. Example: Python ·
🌐
Chilkat
chilkatsoft.com › python_memoryview.asp
Explaining the Python memoryview
A "memoryview" supports multi-dimensional data structures (like NumPy arrays).
🌐
NumPy
numpy.org › doc › 2.2 › user › basics.copies.html
Copies and views — NumPy v2.2 Manual
When operating on NumPy arrays, it is possible to access the internal data buffer directly using a view without copying data around. This ensures good performance but can also cause unwanted problems if the user is not aware of how this works.
🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.memmap.view.html
numpy.memmap.view — NumPy v2.5 Manual
New view of array with the same data · Passing None for dtype is different from omitting the parameter, since the former invokes dtype(None) which is an alias for dtype(np.float64)
🌐
Medium
medium.com › @AlexanderObregon › how-pythons-memoryview-and-buffers-work-23c489fbbabb
How Python’s Memoryview and Buffers Work | Medium
August 11, 2024 - Memoryview: As discussed earlier, memoryview objects provide a way to access the internal data of buffer-enabled objects without copying. They are a flexible tool for data manipulation and can be created from any object that supports the buffer ...
🌐
GitHub
github.com › numpy › numpy › issues › 5935
ndarray does not accept memoryview for buffer= under python2 · Issue #5935 · numpy/numpy
June 2, 2015 - I've discovered that ndarray(buffer=memoryview) fails on python 2: In [1]: sys.version Out[1]: '2.7.10 (default, May 26 2015, 13:16:40) \n[GCC 4.9.2]' In [2]: numpy.__version__ Out[2]: '1.10.0.dev0+9e7a0b2' In [3]: b = bytearray([1,2,3]) In [4]: b Out[4]: bytearray(b'\x01\x02\x03') In [5]: m = memoryview(b) In [6]: m Out[6]: <memory at 0x7fa1f4e59b50> Creating ndarray backed by memoryview fails: In [7]: a = ndarray((3,), buffer=m, dtype=uint8) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-32-1528204f5358> in <module>() ----> 1 a = ndarray((3,), buffer=m, dtype=uint8) TypeError: expected a readable buffer object ·
Author: numpy