复合赋值的属性设置器?

5 投票
4 回答
586 浏览
提问于 2025-04-16 22:10

考虑下面这个简单的例子类,它有一个属性,当你调用它时,会返回一些内部数据的修改版本:

class Foo(object):
    def __init__(self, value, offset=0):
        self._value = value
        self.offset = offset

    @property
    def value(self):
        return self._value + self.offset

    @value.setter
    def value(self, value):
        self._value = value

这个 value.setter 对于普通的赋值操作是没问题的,但在复合赋值(比如加法赋值)时就不太管用了:

>>> x = Foo(3, 2)
>>> x.value
5
>>> x.value = 2
>>> x.value
4
>>> x.value += 5
>>> x.value
11

我们希望的行为是,当你写 x.value += 5 时,它应该等同于 x.value = x._value + 5,而不是 x.value = x.value + 5。有没有办法在 Foo 类内部,利用属性接口来实现这个功能呢?

4 个回答

1

我也遇到了同样的问题,后来用以下方法解决了:

class Foo(object):
    def __init__(self):
        self._y = 0

    @property
    def y(self):
        return self._y + 5

    @y.setter
    def y(self, value):
        value -= 5
        self._y = value


>>> f = Foo()
>>> f.y
5
>>> f.y += 1
>>> f._y
1
>>> f.y
6

这可能是一个解决办法吗?我有没有忽略什么呢?

1

重写 __iadd__ 这个特殊方法。

你需要这么做,因为 += 的意思是“把这个值加上五,然后把结果设为新的值”。如果你想让它明白这个值其实并不是真正的值,你就需要改变 += 操作符的含义。

2

@ezod,你问的这个问题没有直接的方法可以解决,即使使用描述符协议也不行。value属性的这种行为完全打破了+=运算符的基本意义。

撰写回答