Before we get into what memory views are, we need to first understand about Python's buffer protocol.
Python Buffer Protocol
The buffer protocol provides a way to access the internal data of an object. This internal data is a memory array or a buffer.
The buffer protocol allows one object to expose its internal data (buffers) and the other to access those buffers without intermediate copying.
This protocol is only accessible to us at the C-API level and not using our normal codebase.
So, in order to expose the same protocol to the normal Python codebase, memory views are present.
What is a memory view?
A memory view is a safe way to expose the buffer protocol in Python.
It allows you to access the internal buffers of an object by creating a memory view object.
Why buffer protocol and memory views are important?
We need to remember that whenever we perform some action on an object (call a function of an object, slice an array), Python needs to create a copy of the object.
If we have large data to work with (eg. binary data of an image), we would unnecessarily create copies of huge chunks of data, which serves almost no use.
Using the buffer protocol, we can give another object access to use/modify the large data without copying it. This makes the program use less memory and increases the execution speed.
Python memoryview() Syntax
To expose the buffer protocol using
memoryview(), we use this syntax:
memoryview() function takes a single parameter:
- obj - object whose internal data is to be exposed.
objmust support the buffer protocol (bytes, bytearray)
Return value from memoryview()
memoryview() function returns a memory view object.
Example 1: How memoryview() works in Python?
#random bytearray random_byte_array = bytearray('ABC', 'utf-8') mv = memoryview(random_byte_array) # access memory view's zeroth index print(mv) # create byte from memory view print(bytes(mv[0:2])) # create list from memory view print(list(mv[0:3]))
65 b'AB' [65, 66, 67]
Here, we created a memory view object mv from the byte array random_byte_array.
Then, we accessed the mv's 0th index,
'A', and printed it (which gives the ASCII value - 65).
Again, we accessed the mv's indices from 0 and 1,
'AB' , and converted them into bytes.
Finally, we accessed all indices of mv and converted it to a list. Since internally
bytearray stores ASCII value for the alphabets, the output is a list of ASCII values of A, B, and C.
Example 2: Modify internal data using memory view
# random bytearray random_byte_array = bytearray('ABC', 'utf-8') print('Before updation:', random_byte_array) mv = memoryview(random_byte_array) # update 1st index of mv to Z mv = 90 print('After updation:', random_byte_array)
Before updation: bytearray(b'ABC') After updation: bytearray(b'AZC')
Here, we updated the memory view's 1st index to 90, the ASCII value of
Since, the memory view object mv references the same buffer/memory, updating the index in mv also updates random_byte_array.