Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i define a setter for a list with an index or slicing?

With the property and setter decorator I can define getter and setter functions. This is fine for primitives but how do I index a collection or a numpy array? Setting values seems to work with an index, but the setter function doesn't get called. Otherwise the print function in the minimal example would be executed.

class Data:
    def __init__(self):
        self._arr = [0, 1, 2]

    @property
    def arr(self):
        return self._arr

    @arr.setter
    def arr(self, value):
        print("new value set")  # I want this to be executed
        self._arr = value


data = Data()

print(data.arr)  # prints [0, 1, 2]
data.arr[2] = 5
print(data.arr)  # prints [0, 1, 5]
like image 858
Meredith Avatar asked Dec 30 '25 03:12

Meredith


1 Answers

You need to use a secondary class that wraps the indexing/slicing functions onto that object type.

(Credit: inspired by this answer)

class SubData():
    def __init__(self, arr):
        self._arr = arr.copy()

    def __getitem__(self, index):
        print("SubData getter")
        return self._arr[index]

    def __setitem__(self, index, value):
        print("SubData setter")
        self._arr[index] = value
    
    def __str__(self):
        return str(self._arr)

class Data():
    def __init__(self, vals):
        self._arr = SubData(vals)

    @property 
    def arr(self):
        print("Data getter")
        return self._arr
    
    @arr.setter
    def arr(self, value):
        print("Data setter")
        self._arr = value

#--main--
        
>a = Data([1,2,3])

>a.arr[2]=5
Data getter
SubData setter

>print(a.arr)
Data getter
[1, 2, 5]

For more complex behavior such as a 2D array, you would need to check the instance of the index (ie, a.arr[2,5] passes a tuple to index). This you wouldn't have to implement the subclass if you used something like a numpy array which implements these indexes.

like image 136
Mr G Avatar answered Jan 01 '26 17:01

Mr G