[Python-ideas] should `dict` supply a default `__missing__` implementation?

Ethan Furman ethan at stoneleaf.us
Wed Jul 6 01:51:15 EDT 2016


On 07/05/2016 10:11 PM, Matt Gilson wrote:

> This discussion has my brain all twisted up...  I'm going to try to work
> my way through it to make some sense of what we're saying here.
>
>  1. It is pretty easy to provide a subclass with a base `__missing__`
>     implementation, so why should python be responsible for providing
>     that behavior?
>  2. We don't want to encourage subclassing `dict`, so let's not make
>     working with `__missing__` slightly nicer (see 1.)
>  3. Would adding `__missing__` to `dict` actually make working with it
>     slightly nicer anyway?
>  4. Other places in the standard library for creating mappings easily
>     (`UserDict` and `collections.Mapping`) do not support
>     `__missing__``, but it is easy to build that functionality yourself
>     (see 1. and example code below)
>
> Let me know if I left anything out or misrepresented any of the comments
> ... It definitely wasn't my intent.
> As I see it, there are three paths forward.
>
>   * Do nothing.  The status quo probably only surprises one or two users
>     a year, so lets not rock the boat.  Additionally, we can't add
>     _everything_ everywhere.  Things just become a mess if you say "Yes"
>     to every idea and you have to draw the line somewhere.
>   * Add `__missing__` to `dict`.  It might be a simple pass-through
>     method for raising `KeyError`, but hey, maybe it'll simplify a
>     code-path or two.
>     <https://hg.python.org/cpython/file/tip/Objects/dictobject.c#l1723>
>   * Add `__missing__` support to `collections.abc.Mapping`
>     <https://hg.python.org/cpython/file/tip/Lib/_collections_abc.py#l595> (or
>     I guess UserDict, but I'd be just as happy if that one went away
>     completely :-).  I'm sure I haven't thought through all the
>     pitfalls, but (additional documentation aside) it seems like it
>     could be as easy as:
>
>
>
> class Mapping(Sized, Iterable, Container):
>      def __missing__(self, key):
>          raise KeyError
>
>      @abc.abstractmethod
>      def __getitem__(self, key):
>          self.__missing__(key)
>
>      ...

I will admit I don't understand the push-back against adding 
__missing__, and I'm mystified about the comment that users shouldn't be 
subclassing dict.  I thought one of the key advances late in the 2.x 
series was easy(er) subclassing of the builtins.

Unless it's a practicality thing, what with dict being written in such a 
subclass-hostile way (for performance reasions?):

class ADict(dict):

     def __init__(self):
         super(ADict, self).__init__()
         self.names = []

     def __delitem__(self, name):
         if name in self.names:
             self.names.remove(name)
         super(ADict, self).__delitem__(name)

     def __setitem__(self, name, value):
         if name not in self.names:
             self.names.append(name)
         super(ADict, self).__setitem__(name, value)

my_dict = ADict()
my_dict['howdy'] = 'bye'
my_dict.update({'hola': 'adios'})

print(my_dict.names)   # ['howdy']
print(my_dict.items()) # dict_items([('howdy','bye'), ('hola','adios')])

my_dict.pop('howdy')
del my_dict['hola']

print(my_dict.names)   # ['howdy']
print(my_dict.items()) # dict_items([])

--
~Ethan~


More information about the Python-ideas mailing list