Python InfiniteDefaultRevisionDictionary, any implementations?

81 Views Asked by At

In programming, certain dictionary-based data structures are very useful and important. For example:

  1. Revision dictionary: Revision dictionary is a sub-type of dictionary that keeps keys sorted in the order of last modification. It is commonly used in cache handling which remembers most recently used items.

  2. Default dictionary: Default dictionary can return a default element when the dictionary is accessed with a key that is not present in the dictionary. It already has an implementation in collections.defaultdict.

  3. Infinite dictionary: An infinite dictionary can be accessed with infinitely layer of nested recursion, i.e., infinite chaining of keys, e.g., dct[person_name][gender], dct[company_name][employees], it can be used to create dynamic data structures, or even modeling file-system structures.

So my question is that: in Python, is it possible to write a dictionary that has all the 3 features, i.e., an infinite default revision dictionary? In particular, one can specify options during creation, e.g., whether the items should be sorted in the order of insertion, or keys' order, or revision order. And how to implement if possible?

It would be very cool if future-version Python has a built-in Dictionary class that supports all of these features and options.

Edits: Point 2 might not be in contradiction with Point 3, that in principle, an InfiniteDefaultRevisionDictionary can have a default key other than lambda of itself. For example, if the default key is 0, then:

dd=InfiniteDefaultRevisionDictionary(default=0, {})
print(dd['a']['b']['c']) # should give 0
dd['b']['c'][2] = [1, '2', 3.5] # should work fine
1

There are 1 best solutions below

0
xuancong84 On

Thanks to all who have replied! Combining suggestions from various people as well as my own research, below is the most I can do.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
InfiniteDefaultRevisionDict sort items in the order of latest updates and allows arbitrary chaining of keys.

For example,

>>> d=InfiniteDefaultRevisionDict()
>>> dct[person_name][gender] = 'M'
>>> dct[company_name][employees] = [...]
"""

import bisect, json
from collections import namedtuple
from collections.abc import MutableMapping


from collections import OrderedDict, defaultdict

class Dict(OrderedDict):
    def __init__(self, default=None, init_dct={}):
        self._default = default
        self.update(init_dct)

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        self.move_to_end(key)

    def __missing__(self, key):
        self[key] = self._default() if callable(self._default) else self._default
        return self[key]

    def to_json(self, fp=None, **kwargs):
        return json.dumps(self, default=lambda t: dict(t), **kwargs) if fp==None else json.dump(self, fp, default=lambda t: dict(t), **kwargs)

    def from_json(self, fp=None, data=''):
        self.update(json.loads(data, object_hook=lambda t: (Dict(self._default, t) if type(t)==dict else t)) if fp==None \
            else json.load(fp, object_hook=lambda t: (Dict(self._default, t) if type(t)==dict else t)))
        return self


InfiniteDefaultRevisionDict = lambda: Dict(InfiniteDefaultRevisionDict)

It cannot set the default lambda other than InfiniteDefaultRevisionDict. However, you can serialize it to JSON and de-serialize it from JSON in the form of a standard Python dict. Hope someone can come up with a better solution that can satisfy more requirements.