UserDict's has_key() and get() should use __getitem__()

Andrew Dalke dalke at acm.org
Wed Apr 5 18:11:45 EDT 2000


Hamish Lawson wrote:
>I grant that my proposal is a bit less efficient, but I see that
>as part of the cost for the proper abstraction. Given that
>UserDict exists primarily to be subclassed, and usually for the
>purpose of providing new definitions of setting and getting
>items, I do think that UserDict should be implemented in such a
>way as not to require those methods which are conceptually
>dependent to be redefined in the derived class.

I don't believe your estimate, that UserDicts are usually derived
"for the purpose of providing new definitions of setting and
getting items", is correct.

Most of the times I've used UserDict/UserList were to add extra
functionality.  For example, a UserDict which preserves the
input order (modifies __setitem__ and keys; __delitem__ and
items/values should be added, but just needed a quick hack).

Or the Dict is supposed to emulate a dictionary-like format,
so I've had __str__ return the properly formatted string.
(Eg, consider a dictionary for HTML-like tags.)

Only rarely have it used it to do normalization - I try to
push that into the I/O routines.

In addition, in a good OO design, you should be able to use
an instance of a derived class anywhere you use an instance
of a base class.  Your example (a caseless Dict), changes
how/when lookup failures occur.  Thus, a "CaselessDict" really
isn't a type of UserDict, you're just using it for some
implementation reuse.

Instead, you want a minimal interface, which puts the least
amount of assumptions on the class as possible.  This corresponds
to something like:

class AbstractUserDict:
  ...
  def __getitem__(self, key):
    raise NotImplementedError
  def __setitem__(self, key, val):
    raise NotImplementedError
  def keys(self):
    raise NotImplemenetedError
  def has_key(self, key):
    try:
      self[key]
      return 1
    except KeyError:
      return 0
  def items(self):
    items = []
    for key in self.keys():
        items.append(self[key])
    return tuple(items)
  ...

Then Python's UserDict is just an implementation of the
AbstractUserDict base class.

This is the sort of design you need in a stricter compile-time
language like Java or C++.  Because this is Python, you don't
need to tell the complier you're implementing an interface -
you just implement it.  And because this is Python, it's easy to
implement.

                    Andrew
                    dalke at acm.org






More information about the Python-list mailing list