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.

4
  • 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. Commented Apr 11, 2023 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? Commented Apr 11, 2023 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 Commented Apr 11, 2023 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. Commented Apr 11, 2023 at 22:39

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.