dank tagg
dank tagg

Reputation: 259

Proper way to override `__setitem__` and `__getitem__`

I'm trying to subclass dict but can't seem to get it working:

class CacheManager(dict):
    def __init__(self, *args):
        dict.__init__(self, args)
        self.log = ""

    @property
    def length(self):
        return len(self)

    @staticmethod
    def do_log(message:str):
        now = datetime.utcnow().strftime("%d-%b %H-%M-%S")
        template = f"[{now}] {message}\n"
        return template


    def __setitem__(self, key, value):
        self.log += self.do_log(f"SET `{key}` with value `{value}`")
        return dict.__setitem__(key, value)
    
    def __getitem__(self, key):
        self.log += self.do_log(f"GET `{key}` with value `{self.__getitem__(key)}`")
        return dict.__getitem__(key)
cache = CacheManager()
cache["key"] = "value"
cache["key"]

However this returns: TypeError: descriptor '__setitem__' requires a 'dict' object but received a 'str'

I think it has to do with self.log, but is there any way to do that without error?

Upvotes: 0

Views: 561

Answers (1)

chepner
chepner

Reputation: 531165

You forgot to pass self to dict.__setitem__. You can do that implicitly

super().__setitem__(key, value)

or explicitly

dict.__setitem__(self, key, value)

The same applies to __getitem__.

Upvotes: 1

Related Questions