← index #4064Issue #6970
Related · high · value 2.592
QUERY · ISSUE

Missing `memoryview.cast` in MicroPython

openby Pequeopened 2018-08-19updated 2024-10-02
enhancement

It seems memoryview has no cast() method in MicroPython, has it?

Is there another way to create a memoryview out of an array.array('h', array_size) that results in a bytearray-like memory view without making a copy of the buffer?

In code, for better clarity:

import array


size = 64
a = array.array('h', range(size))
m = memoryview(a).cast('B')
assert len(m) == 2 * size
CANDIDATE · ISSUE

Missing attributes

closedby kdschlosseropened 2021-02-27updated 2025-03-03

memoryview iis missing every single attribute/function

c_contiguous
cast
contiguous
f_contiguous
format
hex
itemsize
nbytes
ndim
obj
readonly
release
shape
strides
suboffsets
tobytes
tolist
toreadonly

__iter__ is missing from bytearray, this one is strange because I am able to iterate over a bytearray. Not sure exactly how that is working..

also if I run the following code my ESP32 crashes and then boot loops

for item in dir(memoryview):
    print(item)

but this code does work.

test = bytearray()
for item in dir(memoryview(test)):
    print(item)

I am trying to get access to the underlying bytearray attached to the memory view object. II am doing this because I am using a custom __iter__ method in order to add padding. I have another method that calculates the "width" which is the bit number where the last 1 is found across all bytes in the array.

I have sub classed the memory view object to do this

class Character(memoryview):
    _pad = array.array('B', [0])
    _width = array.array('B', [0])

    @property
    def width(self):
        if self._width[0] == 0:
            for ii in range(8):
                for byte in self.obj:
                    if (byte >> ii) & 1:
                        break
                else:
                    break

            else:
                ii = 1

            self._width[0] = ii + 1
        return self._width[0]

    def pad(self, amount):
        self._pad[0] = amount
        return self

    def __iter__(self):
        res = bytearray([0] * (12 - len(self) + self._pad[0]))
        res += self
        res += bytearray([0] * self._pad[0])
        return iter(memoryview(res))

if you look in the __iter__ method you will notice how I am adding the contents of the memoryview object to a bytearray, strangely this works. but in the width property if I use for byte in self: it is going to use the __iter__ method I created. Doing that does work but the program then has to iterate over bytes that are 0's because of the padding being added. Now I know that I can do the following to help sped things up

for byte in self:
    if byte = 0:
        continue

I shouldn't have to do this, there should be access to the underlying object

I have another question. In CPython if I want to speed up a for loop I am able to do this using list comprehension. Even if I do not set the list into a variable it is going to speed p the processing some 200 times.

def _do():
    # put some code here

[_do() for _ in range(10000000)]

the code above is going to run leaps and bounds faster then the code below.

def _do():
    # put some code here

for _ in range(10000000):
    _do()

is this also the case with MicroPython? I find this to be one of best (if not the best) thing to do when optimizing python code. It makes a huge improvement in the speed in which a program runs if having to iterate over large data sets or even when iterating over smaller data sets often.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied