2
Day 5 and 6 homework Sloetjes
xuanyi.wang edited this page 2023-04-12 01:00:34 +02:00

Xuanyi Wang_Day-5&6_Homework_04/05/23

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._dict_copy = self.__dict__.copy()

    def __setattr__(self, name, value):
        if name != '_dict_copy' and name != '_treasure':
            if self.__dict__ != self._dict_copy:
                print("attribute deleted!")
            self._dict_copy = self.__dict__.copy()
        super().__setattr__(name, value)

    @property
    def treasure(self):
        if self.__dict__ != self._dict_copy:
            print("attribute deleted!")
            self._dict_copy = self.__dict__.copy()
        return self._treasure
An example usage of the Vault class:
vault = Vault()
print(vault.treasure)
Output:
attribute deleted!
gold
Change an attribute of the vault instance
vault.key = 'silver'
Output:
attribute deleted!
Try to access the treasure attribute again
print(vault.treasure)
Output:
attribute deleted!
gold
Another way to implement Vault:
class Vault:
    def __init__(self):
        self._known_attrs = {'treasure': 'gold'}
        self._attrs = self._known_attrs.copy()

    def __getattribute__(self, name):
        if name == 'treasure':
            attrs = object.__getattribute__(self, '_attrs')
            known_attrs = object.__getattribute__(self, '_known_attrs')
            if attrs != known_attrs:
                print('attribute deleted!')
            return attrs[name]
        return object.__getattribute__(self, name)

    def __setattr__(self, name, value):
        if name == 'treasure':
            attrs = object.__getattribute__(self, '_attrs')
            attrs[name] = value
            known_attrs = object.__getattribute__(self, '_known_attrs')
            if attrs != known_attrs:
                print('attribute deleted!')
        else:
            object.__setattr__(self, name, value)
vault = Vault()
print(vault.treasure)
Output:
gold
Change an attribute of the vault instance
vault.treasure = 'silver'
Output:
attribute deleted!

To get the other person's class to return "gold", despite any countermeasures they've implemented:

It can be achieved by creating a new class that inherits from the Vault class and overrides its _treasure attribute.
class OthersVault(Vault):
    def __init__(self):
        super().__init__()
        self._treasure = 'gold'
Create a OthersVault object that inherits all methods and attributes from the Vault class and returns 'gold' as the value of the _treasure attribute:
>>> gv = OthersVault()
>>> gv.treasure
'gold'