Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python cache dictionary - counting number of hits

I'm implementing a caching service in python. I'm using a simple dictionary so far. What I'd like to do is to count number of hits (number of times when a stored value was retrieved by the key). Python builtin dict has no such possibility (as far as I know). I searched through 'python dictionary count' and found Counter (also on stackoverflow), but this doesn't satisfy my requirements I guess. I don't need to count what already exists. I need to increment something that come from the outside. And I think that storing another dictionary with hits counting only is not the best data structure I can get :)

Do you have any ideas how to do it efficiently?

like image 896
ducin Avatar asked Oct 18 '13 06:10

ducin


2 Answers

For an alternative method, if you're using Python 3 (or are willing to add this module to your Python 2 project, which has a slightly different interface), I strongly recommend the lru_cache decorator.

See the docs here. For example, this code :

from functools import lru_cache

@lru_cache(maxsize=32)
def meth(a, b):
    print("Taking some time", a, b)
    return a + b

print(meth(2, 3))
print(meth(2, 4))
print(meth(2, 3))

...will output :

Taking some time 2 3
5
Taking some time 2 4
6
5   <--- Notice that this function result is cached

As per the documentation, you can get the number of hits and misses with meth.cache_info(), and clear the cache with meth.cache_clear().

like image 124
F.X. Avatar answered Sep 28 '22 02:09

F.X.


You can subclass a built-in dict class:

class CustomDict(dict):
    def __init__(self, *args, **kwargs):
        self.hits = {}
        super(CustomDict, self).__init__(*args, **kwargs)

    def __getitem__(self, key):
        if key not in self.hits:
            self.hits[key] = 0
        self.hits[key] += 1
        return super(CustomDict, self).__getitem__(key)

usage:

>>> d = CustomDict()
>>> d["test"] = "test"
>>> d["test"]
'test'
>>> d["test"]
'test'
>>> d.hits["test"]
2
like image 36
freakish Avatar answered Sep 28 '22 02:09

freakish