From b4ad845d12faf5923370cc47e9e5889acf2f3a72 Mon Sep 17 00:00:00 2001 From: Luciano Ramalho Date: Mon, 2 Aug 2021 22:00:17 -0300 Subject: [PATCH] missing.py example --- 03-dict-set/missing.py | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 03-dict-set/missing.py diff --git a/03-dict-set/missing.py b/03-dict-set/missing.py new file mode 100644 index 0000000..609d39e --- /dev/null +++ b/03-dict-set/missing.py @@ -0,0 +1,122 @@ +""" +Semantics of ``__missing__`` across mappings. + +✅ = indicates ``__missing__`` was called + +Subclass of ``dict``:: + + >>> d = DictSub(A = 'letter A') + >>> d['a'] # ✅ + 'letter A' + >>> d.get('a', '') + '' + >>> 'a' in d + False + +Subclass of ``UserDict``:: + + >>> ud = UserDictSub(A = 'letter A') + >>> ud['a'] # ✅ + 'letter A' + >>> ud.get('a', '') # ✅ + 'letter A' + >>> 'a' in ud + False + + +Simple subclass of ``abc.Mapping``:: + + >>> sms = SimpleMappingSub(A = 'letter A') + >>> sms['a'] + Traceback (most recent call last): + ... + KeyError: 'a' + >>> sms.get('a', '') + '' + >>> 'a' in sms + False + + +Subclass of ``abc.Mapping`` with support for ``__missing__``:: + + >>> mms = MappingMissingSub(A = 'letter A') + >>> mms['a'] # ✅ + 'letter A' + >>> mms.get('a', '') # ✅ + 'letter A' + >>> 'a' in mms # ✅ + True + +Subclass of ``abc.Mapping`` with support for ``__missing__``:: + + >>> dms = DictLikeMappingSub(A = 'letter A') + >>> dms['a'] # ✅ + 'letter A' + >>> dms.get('a', '') + '' + >>> 'a' in dms + False + + +""" + +from collections import UserDict +from collections import abc + + +def _upper(x): + try: + return x.upper() + except AttributeError: + return x + + +class DictSub(dict): + def __missing__(self, key): + return self[_upper(key)] + + +class UserDictSub(UserDict): + def __missing__(self, key): + return self[_upper(key)] + + +class SimpleMappingSub(abc.Mapping): + def __init__(self, *args, **kwargs): + self._data = dict(*args, **kwargs) + + # next three methods: abstract in ABC + def __getitem__(self, key): + return self._data[key] + + def __len__(self): + return len(self._data) + + def __iter__(self): + return iter(self._data) + + # never called by instances of this class + def __missing__(self, key): + return self[_upper(key)] + + +class MappingMissingSub(SimpleMappingSub): + def __getitem__(self, key): + try: + return self._data[key] + except KeyError: + return self[_upper(key)] + + +class DictLikeMappingSub(SimpleMappingSub): + def __getitem__(self, key): + try: + return self._data[key] + except KeyError: + return self[_upper(key)] + + def get(self, key, default=None): + return self._data.get(key, default) + + def __contains__(self, key): + return key in self._data