0

I used super() as a part of the __setattr__ method to update a dictionary whenever an attribute value is set on an instance of a class; however, a warning reported as my class object has no such attribute '_attributes'. The code just like this:

class Vault:
    def __init__(self):
        self._treasure = "gold"
        self._attributes = dict(self.__dict__)

    def __setattr__(self, name, value):
        if name != "_attributes" and name not in self._attributes:
            print("attribute deleted!")
        self._attributes[name] = value
        super().__setattr__("_attributes", dict(self.__dict__))

    @property
    def treasure(self):
        if self.__dict__ != self._attributes:
            print("attribute deleted!")
        return self._treasure

v = Vault()
print(v.treasure)

Maybe there is an issue caused by the super()? I was new to use this method in Python and I was not sure, can someone help to explain it a bit? Another problem occurred as I initally thought the problem was caused by the line self._attributes[name] = value inside the __setattr__ method since '_attributes' had not yet defined when the instance is created, so I fixed my code as below but it still not work. The warning reported a Recursion Error saying that the maximum recursion depth exceeded.

class Vault:
    def __init__(self):
        self._treasure = "gold"

    def __setattr__(self, name, value):
        if name != "_attributes" and name not in self.__dict__:
            print("attribute deleted!")
        self.__dict__[name] = value
        self._attributes = dict(self.__dict__)

    @property
    def treasure(self):
        if self.__dict__ != self._attributes:
            print("attribute deleted!")
        return self._treasure

v = Vault()
print(v.treasure)

It will be super appreciated if someone may help me with this __setattr__ method and the bug fixing. This question is for my Python study and development, so it welcomes any answers and discussions. The goal of this code is to create a class named 'Vault' containing an attribute named 'treasure' which returns 'gold' under normal circumstances, but a warning message such as 'attribute deleted' if it detects any of its attributes have been changed.

  • 1
    The first time `__setattr__` is called is in `__init__` when you do: `self._treasure = "gold"`. And indeed, at this point, there is no `self._attributes`. – juanpa.arrivillaga Apr 11 '23 at 22:28
  • " but a warning message such as 'attribute deleted' if it detects any of its attributes have been changed." can you elaborate on this? When should this be printed? – juanpa.arrivillaga Apr 11 '23 at 22:29
  • 1
    Anyway, one thing you could do is just use `object.__setattr__(self, "treasure", "gold")` and `object.__setattr__(self, "_attributes", self._attributes = dict(self.__dict__))` etc inside your implementation – juanpa.arrivillaga Apr 11 '23 at 22:31
  • Specifically, your `__init__` in your original implementation need to use `object.__setattr__()` (or `super().__setattr__()`) for `_attribute` as your class's `__setattr__` has been overridden, if your intention is to define `_attribute` is the mapping to store attributes. – metatoaster Apr 11 '23 at 22:39

0 Answers0