I want to read a file into a memory buffer (binary sequence type—bytes, bytearray or memoryview) and then be able to pass that into functions/methods without a copy. I understand that memoryview is intended to avoid copying:
memoryview objects allow Python code to access the internal data of an object that supports the buffer protocol without copying.
But I can't tell if there's a practical difference. I know that arguments get passed into functions by val, but gather for binary sequence types that the value passed is a reference to the buffer, not a copy. At least, that's what experimentation suggested to me:
>>> class MyClass():
... def __init__(self, data:bytearray):
... data[0] = 42
...
>>> x = bytearray([0, 1, 2])
>>> x
bytearray(b'\x00\x01\x02')
>>> y = MyClass(x)
>>> x
bytearray(b'*\x01\x02')
The bytearray x from the calling context was modified within the MyClass constructor. That's consistent with this note:
Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).
I can't do a similar experiment with bytes or memoryview objects since those are immutable. But that note suggests to me it would be the same.
So, what's a situation in which there'd be a practical difference?
Also, if a bytearray was wrapped into io.BytesIO and passed as an argument, would that be passed as an object reference?
(I'm trying to figure out how to handle the data efficiently without creating copies of data in memory unless explicitly needed.)