[Python] subclass numpy arrays: when using resize, how to re-attach the view to sliced...

Discussão em 'Python' iniciado por Stack, Maio 2, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to create a buffer array that creates extra indexes of the numpy so I can assign rather than using functions like np.append and where "children" sliced array can still be a view from the parent. My code below can do this, but I also want to include the functionality such that when self.resize() is called on the parent array, it will trigger a callback that will send the parent back to the child and "re-attach" the parent to the child.

    From the code below, we can see that the child's memory address has changed, but it's not the same as the parent's. I tried slicing the parent into the child (child[:] = parent[child.idx:], but he error ValueError: cannot resize this array: it does not own its data

    Is there anyway to do this?

    class BufferArray(np.ndarray):
    GROWTH = 2
    def __new__(cls, input_array):
    base = np.asarray(input_array, dtype=float)
    n = base.size
    cap = max(1, 2 * n)
    obj = super().__new__(cls, shape=(cap,), dtype=base.dtype)
    obj[:n] = base
    obj[n:] = np.nan
    obj.n = n
    return obj

    def __array_finalize__(self, obj):
    if obj is None:
    return
    self.n = getattr(obj, "n", 0)

    def _grow(self):
    old = self.size
    self.resize(old * self.GROWTH, refcheck=False)
    self[old:] = np.nan
    if getattr(self, "mirror_callbacks", False):
    if len(self.mirror_callbacks) > 0:
    for callback in list(self.mirror_callbacks):
    callback(self)

    def update_value(self, value):
    if self.n >= self.size:
    self._grow()
    self[self.n] = value
    self.n += 1

    def _attach_mirror(self, mirror):
    print(f"\n_attach_mirror called")
    print(f"parent id: {id(mirror)}")
    print(f"child id before: {id(self)}")
    #self._grow() # returns ValueError: cannot resize this array: it does not own its data
    #self[:] = mirror[self.mirror_idx:] # returns ValueError: cannot resize this array: it does not own its data
    self = mirror.create_mirror(self.mirror_idx)
    print(f"child id after: {id(self)}")

    def _add_mirror_callbacks(self, callback):
    if not getattr(self, "mirror_callbacks", False):
    self.mirror_callbacks=[callback]
    else:
    self.mirror_callbacks.append(callback)

    def create_mirror(self, idx):
    slice = self[idx:]
    slice.mirror_idx = idx
    self._add_mirror_callbacks(slice._attach_mirror)
    return slice

    parent = BufferArray(np.zeros(2, dtype=int))
    child = parent.create_mirror(1)

    print(f"parent id: {id(parent)}")
    print(f"child id: {id(child)}")
    print(f"parent: {parent}")
    print(f"child: {child}")

    print(f"\nlooping")
    for i in range(1, 4):
    parent.update_value(10*i)
    print("\n")
    print(f"parent: {parent}")
    print(f"parent.n: {parent.n}")
    print(f"child: {child}")
    print(f"child.n: {child.n}")

    print(f"\nfinal")
    print(f"parent: {parent}")
    print(f"child: {child}")

    Continue reading...

Compartilhe esta Página