DEV Community

Discussion on: defaultdicts: Never Check If a Key is Present Again!

Collapse
 
karolyi profile image
László Károlyi

I know dicts are ordered by default from 3.7 onwards (so you could just use defaultdict), but I needed to mix the defaultdict and OrderedDict at one point. Introducing the DefaultOrderedDict:

from collections import OrderedDict
from copy import deepcopy


class DefaultOrderedDict(OrderedDict):
    """Extending getter functions to provide defaults."""
    _default = dict()

    def __init__(self, *args, default, **kwargs):
        self._default = default
        super().__init__(*args, **kwargs)

    def __getitem__(self, key):
        if key in self:
            return self.get(key)
        value = self[key] = deepcopy(self._default)
        return value

    def __deepcopy__(self, memo):
        """Return a deep copy of self."""
        obj = DefaultOrderedDict(default=self._default)
        for key, value in self.items():
            obj[key] = deepcopy(value)
        return obj

one example of how it can be used:

terms_by_func = DefaultOrderedDict(default=[])

it will basically deepcopy() the contents of the default value.

Collapse
 
rpalo profile image
Ryan Palo

Neat! My first thought was to wonder if it could be done with multiple inheritance between defaultdict and OrderedDict, but that seems like that could be a big nightmare, so your method is probably cleaner. :)