How can I change a read-only property?

I have two classes: one with an override of the in-place operator (say +=), and the other an instance of the first with @property. (Note: this greatly simplifies from my actual code to a minimum that reproduces the problem.)

class MyValue(object):
    def __init__(self, value):
        self.value = value

    def __iadd__(self, other):
        self.value += other
        return self

    def __repr__(self):
        return str(self.value)

class MyOwner(object):
    def __init__(self):
        self._what = MyValue(40)

    @property
    def what(self):
        return self._what

Now when I try to use this operator for a public property:

>>> owner = MyOwner()
>>> owner.what += 2
AttributeError: can't set attribute

From what I found, this is to be expected, since it is trying to set the property on owner. Is there a way to prevent setting the property on a new object, but still allowing me (in place) to modify the object behind it, or is it just a fad of the language?

(. , , , , , Python 3.)


, .

class MyValue(object):
    # ... 

    def add(self, other):
        self.value += other

>>> owner = MyOwner()
>>> owner.what.add(2)
>>> print(owner.what)
42
+4
1

; object += value :

object = object.__iadd__(value)

, . , self, no-op .

object , :

owner.what = owner.what.__iadd__(2)

, object.what (, tmp = owner.what; tmp += 2), .

, :

class MyOwner(object):
    def __init__(self):
        self._what = MyValue(40)

    @property
    def what(self):
        return self._what

    @what.setter
    def what(self, newwhat):
        if newwhat is not self._what:
            raise AttributeError("can't set attribute")
        # ignore the remainder; the object is still the same
        # object *anyway*, so no actual assignment is needed

:

>>> owner = MyOwner()
>>> owner.what
40
>>> owner.what = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 24, in what
AttributeError: can't set attribute
>>> owner.what += 2
>>> owner.what
42
+5

Source: https://habr.com/ru/post/1648816/


All Articles