classification
Title: MutableMapping code smell (see OrderedDict)
Type: Stage:
Components: Library (Lib) Versions: Python 3.1
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: aronacher, georg.brandl, jimjjewett, pitrou, rhettinger
Priority: low Keywords:

Created on 2009-03-02 04:10 by jimjjewett, last changed 2009-03-02 09:41 by rhettinger. This issue is now closed.

Messages (2)
msg82999 - (view) Author: Jim Jewett (jimjjewett) Date: 2009-03-02 04:10
Copy of issue 5397

In python 3, UserDict (and DictMixin) are gone; presumably they should 
be replaced by either a dict subclass or the ABC MutableMapping.

Unfortunately, there doesn't seem to be a clean way to inherit from 
both.  

In python 2.x, you could write

  class MyDict(DictMixin, dict): ...

but with

  class MyDict(MutableMapping, dict): ...

MutableMapping explicitly overrides __getitem__, __setitem__, and 
__delitem__ to raise a KeyError.

The OrderedDict implementation in issue 5397 puts the concrete class 
first, and then handles composite methods manually, by either rewriting 
them (repr, copy) or explicitly delegating past dict and straight to 
MutableMapping (setdefault, update, etc.)

Both solutions seem fragile.  

Unfortunately, the closest I come to a solution is to split the ABC 
into a Mixin portion and an ABC enforcer.

    # The concrete methods of the current ABC
    class MapMixin: 

    # The abstract methods that get checked
    class MutableMapping(MapMixin):

# Trust that dict will always implement 
# all required concrete methods for us
class MyDict(MapMixin, dict):
msg83010 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2009-03-02 09:41
FWIW, I'm happy with Guido's design of MutableMapping.  It parallels all
the other ABCs in its design and it succeeds completely at its primary
role as a defining an interface.  Its secondary role is to provide some
mixin capability.  It does well in this role when used as documented
(just filling-in the abstract methods as letting the mixin do the rest).

The case with OrderedDict is not a typical use of mixins because the
primary class (dict) already provides all of methods demanded by the
interface.  I explicitly overwrite some of dict's methods because that
is part of the behavior that OrderedDict wants to define differently
than dict.  It is appropriate that the primary class gets first dibs on
defining a method and that intentional overrides are done explicitly (as
they are in the OrderedDict example).

With OrderedDict, the only reason we subclassed from dict was to provide
interoperability with third-party tools that may have been hardwired to
work only with dicts.   In general, the preferred approach is to not
subclass both dict and OrderedDict and to let the MutableMapping
interface do its job.

The proposed splitting of MutableMapping looks unhealthy and overly
complex to me.  It makes ABCs harder to use in the general case just to
make one special case look a little prettier and do more of its magic
implicitly.

If this *really* bugs you, OrderedDict doesn't have to inherit from
MutableMapping at all.  We can throw code reuse out the window and just
duplicate the relevant code fragments.  To my eyes, either way is an
explicit override of the dict's methods which is the intended effect.

FWIW, the UserDict class in Py3.x was relocated to the collections
module.  It isn't gone.  We made an effort to kill it but found that
there were compelling use cases that were not a cleanly solved by any
other approach.
History
Date User Action Args
2009-03-02 09:41:51rhettingersetmessages: - msg83006
2009-03-02 09:41:35rhettingersetstatus: open -> closed
resolution: wont fix
messages: + msg83010
2009-03-02 07:10:03rhettingersetpriority: low
assignee: rhettinger
messages: + msg83006
2009-03-02 04:10:52jimjjewettcreate