What do you think of this idea? It's supposed to be a dict that makes a reasonable guess at the key you were trying to access for getters and deleters. Setters should be untouched.
Similar to how tab completion in bash works, if some command you are typing only has one reasonable completion then pressing tab will fill it out for you.
The logic should be like this, if the query_key is not in the dict but there is only one dict_key satisfying the expression query_key in dict_key
then we can assume that is the key. For string keys, additionally, it should be case-insensitive.
class FriendlyDict(dict):
def _guess_key_or_die(self, q):
possibilities = []
for key in self:
try:
if q in key or q.lower() in key.lower():
possibilities.append(key)
except (TypeError, AttributeError):
pass
if len(possibilities) == 1:
return possibilities[0]
err = KeyError(q)
err.data = possibilities
raise err
def __getitem__(self, key):
try:
return super(FriendlyDict, self).__getitem__(key)
except KeyError:
guess = self._guess_key_or_die(key)
return super(FriendlyDict, self).__getitem__(guess)
def __delitem__(self, key):
try:
return super(FriendlyDict, self).__delitem__(key)
except KeyError:
guess = self._guess_key_or_die(key)
return super(FriendlyDict, self).__delitem__(guess)
def __contains__(self, key):
if super(FriendlyDict, self).__contains__(key):
return True
try:
self._guess_key_or_die(key)
except KeyError:
return False
else:
return True
- Are there any more
__dunder__
methods which really should be overridden? - Are there any gotchas I may have missed which might make the class behave in weird/unpredictable ways?
- Are there any other nice features that could be added which are consistent with the general idea of this?
- Is it better as a subclass or would it be possible to make it a mixin to use with other types of mappings, e.g.
OrderedDict
?