python缓存字典 - 计算命中数

时间:2013-10-18 06:57:13

标签: python caching dictionary count

我正在python中实现一个缓存服务。到目前为止我正在使用一本简单的字典。我想要做的是计算点击次数(按键检索存储值的次数)。 Python内置词典没有这种可能性(据我所知)。我搜索了'python dictionary count'并找到Counter(也在stackoverflow上),但这不符合我的要求。我不需要计算已经存在的东西。我需要增加来自外部的东西。我认为存储另一个只有点击计数的字典并不是我能得到的最好的数据结构:)

你有什么想法如何有效地做到这一点?

5 个答案:

答案 0 :(得分:3)

您可以继承内置dict类:

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)

用法:

>>> d = CustomDict()
>>> d["test"] = "test"
>>> d["test"]
'test'
>>> d["test"]
'test'
>>> d.hits["test"]
2

答案 1 :(得分:3)

对于另一种方法,如果您正在使用Python 3(或者愿意将this module添加到您的Python 2项目(其界面略有不同)),我强烈推荐lru_cache装饰器

查看文档here。例如,此代码:

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))

...将输出:

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

根据文档,您可以使用meth.cache_info()获取点击次数和未命中次数,并使用meth.cache_clear()清除缓存。

答案 2 :(得分:1)

使用另一个字典存储命中计数可能不是一个糟糕的选择,但你也可以这样做:

class CacheService(object):

    def __init__(self):
        self.data = {}

    def __setitem__(self, key, item):
        self.data[key] = [item, 0]

    def __getitem__(self, key):
        value = self.data[key]
        value[1] += 1
        return value[0]

    def getcount(self, key):
        return self.data[key][1]

您可以使用以下内容:

>>> cs = CacheService()
>>> cs[1] = 'one'
>>> cs[2] = 'two'
>>> print cs.getcount(1)
0
>>> cs[1]
'one'
>>> print cs.getcount(1)
1

答案 3 :(得分:0)

只是重载内置的dict数据类型会容易得多。这将解决您的问题。

def CountDict(dict):
    count = {}

    def __getitem__(self, key):
        CountDict.count[key] = CountDict.count.get(key, 0) + 1
        return super(CountDict, self).__getitem__(self, key)

    def __setitem__(self, key, value):
        return super(CountDict, self).__setitem__(self, key, value)

    def get_count(self, key):
        return CountDict.count.get(key, 0)

这将为您提供更多灵活性。就像你可以有两个计数,一个读取数量和另一个读取数量,如果你希望没有太多的复杂性。要了解有关超级的更多信息,请参阅here

编辑以满足OP需要保持读取密钥的计数。可以通过调用get_count方法获得输出。

>>>my_dict = CountDict()
>>>my_dict["a"] = 1
>>>my_dict["a"]
>>>1
>>>my_dict["a"]
>>>1
>>>my_dict.get_count("a")
>>>2

答案 4 :(得分:0)

免责声明:我是kids.cache的作者

您可能需要检查kids.cache这是一个简单的库,默认情况下使用dict作为缓存存储,并将返回包含 hits 的缓存统计信息未命中

实施例

>>> from kids.cache import cache

>>> @cache
... def meth(a, b):
...     print("Taking some time", a, b)
...     return a + b

一次失误和一击:

>>> meth(1, 2)        ## Miss !
Taking some time 1 2
3
>>> meth(1, 2)        ## Hit !
3

让我们添加一个小姐:

>>> meth(1, 3)        ## Miss !
Taking some time 1 2
4

现在让我们问一下缓存信息:

>>> meth.cache_info()
CacheInfo(type='dict', hits=1, misses=2, maxsize=None, currsize=2)

进一步

您可以查看the source code of kids.cache以了解如何实施缓存信息。请注意,它不会将统计信息存储在缓存存储区中。它是保存值的缓存函数。

我相信这是最干净的方式,因为它允许您使用各种缓存存储(以及一些像旧的dict一样简单)而无需在每个存储中实现缓存统计功能。最后一个想法来自Thomas Kemmer撰写的优秀cachetools

您也可以使用kids.cache开箱即用的{{1}}。它没有依赖关系,只有一个文件,在python2和python3上工作,使用起来很简单,同时在必要时允许复杂的缓存。