Page 1 of 2

Resetting bytearray

Posted: Wed Oct 05, 2016 9:53 am
by danielm
How to "reset" bytearray (set all bytes to b'\x00') without being re-allocated?

After doing this function id() should return same value as before.

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 10:34 am
by deshipu
The obvious solution would be:

Code: Select all

for i in range(len(your_array)):
    your_array[i] = 0

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 11:12 am
by platforma
One more option is

Code: Select all

arr[:] = b'0' * len(arr)

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 12:01 pm
by kfricke
platforma wrote:One more option is

Code: Select all

arr[:] = b'0' * len(arr)
Does this really not re-allocate the buffer?

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 12:13 pm
by platforma
At least not from what I tried on unix port:

Code: Select all

>>> arr = bytearray([1,2,3])
>>> arr
bytearray(b'\x01\x02\x03')
>>> id(arr)
140355047877312
>>> arr[:] = b'0' * len(arr)
>>> arr
bytearray(b'000')
>>> id(arr)
140355047877312

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 12:23 pm
by deshipu
It allocates a new buffer, and then copies it over to the old one.

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 12:26 pm
by deshipu
The below code could be much more memory-efficient, unfortunately it's not working:

Code: Select all

>>> a[:] = (b'0' for i in range(10))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NotImplementedError: array/bytes required on right side

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 1:00 pm
by markxr
I used:

Code: Select all

tempbuf = bytearray() 

# ...

tempbuf[::] = b''
Is that ok, or not?

Re: Resetting bytearray

Posted: Wed Oct 05, 2016 1:47 pm
by deshipu
No, that truncates the array to make it 0-element long.

Re: Resetting bytearray

Posted: Fri Oct 07, 2016 9:57 am
by pythoncoder

Code: Select all

$ ./upython 
MicroPython v1.8.1-39-gdb4addd on 2016-07-01; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> a = bytearray(10)
>>> id(a)
139728051341376
>>> a[:] = b'\1' * len(a)
>>> id(a)
139728051341376
>>> a
bytearray(b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01')
>>> a[:] = b'\0' * len(a)
>>> a
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> id(a)
139728051341376
>>> 
While this preserves the ID, I assume a bytes object is temporarily allocated before being copied to the original. Aside from the original suggestion from @deshipu I can see two ways to avoid allocation. One, if speed is critical, would be to implement the original solution using inline assembler. The other would be to define a bytes instance for copying and freeze it as bytecode.