暂时将键和值保留在字典中

nif*_*eco 3 python datetime dictionary

我有一个 python 字典,它不时添加信息。

状况:

  1. 字典中的键始终不应超过 3 个。如果需要添加另一个键值对,则应删除此时字典中最早添加的键,并添加新的键值对。
  2. 添加键值后,1 天后应将其删除。

例子:

result = {}

def add_key(key, val):
    test = result.get(key) # Test to see if key already exists
    if test is None:
        if len(result.keys()) < 3:
            result[key] = val # This key and pair need to be deleted from the dictionary after
                            # 24 hours
        else:
            # Need code to remove the earliest added key.

add_key('10', 'object 2')

## Need another code logic to delete the key-value pair after 24 hours
Run Code Online (Sandbox Code Playgroud)

我应该如何处理这个问题?

mar*_*eau 5

这是我在您的问题 \xe2\x80\x94 下的评论中建议的方法,即通过实现一个字典子类来实现,该子类通过它内部维护的关于它包含的每个值的元数据来完成所需的操作。

\n

这可以通过模块中容器的抽象基类相当容易地完成,collections.abc因为它最大限度地减少了需要在子类中实现的方法的数量。在本例中abc.MutableMapping是在基类中使用的。

\n

请注意,我添加了一个名为的新方法,prune()该方法显示如何删除所有早于指定数量的条目。除此之外,我在print()代码中留下了一些无关的调用,以便在测试 \xe2\x80\x94 时更清楚地显示它正在执行的操作,您可能希望将其删除。

\n
from collections import abc\nfrom datetime import datetime, timedelta\nfrom operator import itemgetter\nfrom pprint import pprint\nfrom time import sleep\n\n\nclass LimitedDict(abc.MutableMapping):\n    LIMIT = 3\n\n    def __init__(self, *args, **kwargs):\n        self._data = dict(*args, **kwargs)\n\n        if len(self) > self.LIMIT:\n            raise RuntimeError(f\'{type(self).__name__} initialized with more \'\n                               f\'than the limit of {self.LIMIT} items.\')\n\n        # Initialize value timestamps.\n        now = datetime.now()\n        self._timestamps = {key: now for key in self._data.keys()}\n\n    def __getitem__(self, key):\n        return self._data[key]\n\n    def __setitem__(self, key, value):\n        if key not in self:  # Adding a key?\n            if len(self) >= self.LIMIT:   # Will doing so exceed limit?\n                # Find key of oldest item and delete it (and its timestamp).\n                oldest = min(self._timestamps.items(), key=itemgetter(1))[0]\n                print(f\'deleting oldest item {oldest=} to make room for {key=}\')\n                del self[oldest]\n\n        # Add (or update) item and timestamp.\n        self._data[key], self._timestamps[key] = value, datetime.now()\n\n    def __delitem__(self, key):\n        """Remove item and associated timestamp."""\n        del self._data[key]\n        del self._timestamps[key]\n\n    def __iter__(self):\n        return iter(self._data)\n\n    def __len__(self):\n        return len(self._data)\n\n    def prune(self, **kwargs) -> None:\n        """ Remove all items older than the specified maximum age.\n\n        Accepts same keyword arguments as datetime.timedelta - currently:\n        days, seconds, microseconds, milliseconds, minutes, hours, and weeks.\n        """\n        max_age = timedelta(**kwargs)\n        now = datetime.now()\n        self._data = {key: value for key, value in self._data.items()\n                        if (now - self._timestamps[key]) <= max_age}\n        self._timestamps = {key: self._timestamps[key] for key in self._data.keys()}\n\n\n\nif __name__ == \'__main__\':\n\n    ld = LimitedDict(a=1, b=2)\n    pprint(ld._data)\n    pprint(ld._timestamps)\n    sleep(1)\n    ld[\'c\'] = 3  # Add 3rd item.\n    print()\n    pprint(ld._data)\n    pprint(ld._timestamps)\n    sleep(1)\n    ld[\'d\'] = 4  # Add an item that should cause limit to be exceeded.\n    print()\n    pprint(ld._data)\n    pprint(ld._timestamps)\n    ld.prune(seconds=2) # Remove all items more than 2 seconds old.\n    print()\n    pprint(ld._data)\n    pprint(ld._timestamps)\n
Run Code Online (Sandbox Code Playgroud)\n