复合赋值的属性设定者?

时间:2011-07-24 15:56:20

标签: python

考虑以下简单示例类,该类具有在调用时公开某些内部数据的修改版本的属性:

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 个答案:

答案 0 :(得分:2)

@ezod,即使使用描述符协议,也没有直接的方法来做你要求的事情。 value属性的那种行为完全打破了+=运算符的语义。

答案 1 :(得分:1)

覆盖__iadd__魔法。

您需要这样做,因为+= 表示“获取值并添加五个,然后将其设置为结果”。如果您希望它知道该值实际上不是值,则需要更改+=运算符的语义。

答案 2 :(得分:0)

  

期望的行为是x.value + = 5应该相当于   x.value = x._value + 5

为什么Python应该知道您的属性是如何实现的(即setter将其值精确地分配给_x)?

property协议允许您为一个名称分配不同的操作(获取,设置,删除)。此协议并不关心这些操作的实现方式。

因此,如果Python对您的代码做出一些假设并尝试修改严格的正向代码逻辑,那将会非常容易混淆。

答案 3 :(得分:0)

我遇到了同样的问题,并用以下方法解决了这个问题:

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

这可能是一个解决方案吗?我忽略了什么吗?