如何为带有索引或切片的列表定义setter?

问题描述 投票:0回答:2

使用 property 和 setter 装饰器,我可以定义 getter 和 setter 函数。这对于基元来说很好,但是如何索引集合或 numpy 数组呢? 设置值似乎可以与索引一起使用,但 setter 函数不会被调用。否则,将执行最小示例中的打印函数。

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]
python-3.x properties setter
2个回答
0
投票

如果您只想对类实例的一个列表执行此操作,您可以通过使用类的 __set_item__

__get_item__
dunder 方法来
以某种方式
执行此操作:

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 inner list set")
        self._arr = value

    def __setitem__(self, key, value):
        print("new value set")
        self._arr[key] =  value

    def __getitem__(self, key):
        return self._arr[key]

data = Data()

print(data.arr)

data[2] = 5
print(data.arr) 

data.arr = [42, 43]
print(data.arr) 

输出:

[0, 1, 2]

new value set        # by    data[2] = 5           using __set_item__
[0, 1, 5]

new inner list set   # by    data.arr = [42, 43]   using @arr.setter
[42, 43]

这仅适用于一个列表成员,因为

__set_item__
正在处理类实例本身,而不是类实例成员的列表。


0
投票

您需要使用一个辅助类将索引/切片函数包装到该对象类型上。例如,这就是在 numpy 数组中使用切片时发生的情况。

(来源:受到this答案的启发)

    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]

对于更复杂的行为,例如二维数组,您需要检查索引的实例(即,

a.arr[2,5
将元组传递给索引)。

© www.soinside.com 2019 - 2024. All rights reserved.