The assignment for tonight is to write 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. You can use the descriptor protocol (set, etc) to detect if its attributes have been changed, and it will have to check its own dict against a known good copy before accessing the treasure attribute to make sure that the attributes are what they're supposed to be.
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
In this implementation, the init method initializes the Vault instance with a treasure attribute set to "gold", as well as a _attributes attribute that is a copy of the instance's dict.
The setattr method is overridden to check whether a new attribute is being added to the instance, and if so, whether the attribute already existed in the _attributes dictionary. If the attribute did not exist in _attributes, it means that it has been added to the instance after initialization, and so a warning message is printed. The _attributes dictionary is then updated with the new attribute, and a new copy of the instance's dict is stored in the _attributes attribute.
Finally, the treasure property is defined to return the value of the _treasure attribute, but only if the instance's dict matches the _attributes dictionary. If any attributes have been added or deleted since initialization, a warning message is printed instead.