Typed memoryviews

C and NumPy arrays as well as the built-in bytes, bytearray, and array.array objects are similar in the sense that they all operate on a contiguous memory area (also called memory buffer). Cython provides a universal interface--the typed memoryview--that unifies and simplifies the access to all these data types.

A memoryview is an object that maintains a reference on a specific memory area. It doesn't actually own the memory, but it can read and change its contents; in other words, it is a view on the underlying data. Memoryviews can be defined using a special syntax. For example, we can define a memoryview of int and a  two-dimensional memoryview of double in the following way:

    cdef int[:] a 
cdef double[:, :] b

The same syntax applies to the declaration of any type in variables, function definitions, class attributes, and so on. Any object that exposes a buffer interface (for example, NumPy arrays, bytes, and array.array objects) will be bound to the memoryview automatically. For example, we can bind the memoryview to a NumPy array using a simple variable assignment:

    import numpy as np 

cdef int[:] arr
arr_np = np.zeros(10, dtype='int32')
arr = arr_np # We bind the array to the memoryview

It is important to note that the memoryview does not own the data, but it only provides a way to access and change the data it is bound to; the ownership, in this case, is left to the NumPy array. As you can see in the following example, changes made through the memoryview will act on the underlying memory area and will be reflected in the original NumPy structure (and vice versa):

    arr[2] = 1 # Changing memoryview 
print(arr_np)
# [0 0 1 0 0 0 0 0 0 0]

In a certain sense, the mechanism behind memoryviews is similar to what NumPy produces when we slice an array. As we have seen in Chapter 3, Fast Array Operations with NumPy and Pandas, slicing a NumPy array does not copy the data but returns a view on the same memory area, and changes to the view will reflect on the original array.

Memoryviews also support array slicing with the standard NumPy syntax:

    cdef int[:, :, :] a 
arr[0, :, :] # Is a 2-dimensional memoryview
arr[0, 0, :] # Is a 1-dimensional memoryview
arr[0, 0, 0] # Is an int

To copy data between one memoryview and another, you can use syntax similar to slice assignment, as shown in the following code:

    import numpy as np 

cdef double[:, :] b
cdef double[:] r
b = np.random.rand(10, 3)
r = np.zeros(3, dtype='float64')

b[0, :] = r # Copy the value of r in the first row of b

In the next section, we will use the typed memoryviews to declare types for the arrays in our particle simulator.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.205.21