4540l2.txt

Listing 2. A Mix-in for Uniform Value Access

class NamedValueError(KeyError):
    pass


class _NoDefault:
    pass


class NamedValueAccessible:

    def valueForKey(self, key, default=_NoDefault):
         ''' Suppose key is 'foo'. This method returns the value with the following precedence:
                   1. Methods before non-methods
                   2. Public attributes before private attributes

              More specifically, this method then returns one of the following:
                   * self.foo()
                   * self._foo()
                   * self.foo
                   * self._foo

              ...or default, if it was specified,
              otherwise raises an exception.
         '''
         assert key
         klass    = self.__class__
         underKey = '_' + key
         attr     = None
         method   = getattr(klass, key, None)
         if not method:
              method = getattr(klass, underKey, None)
              if not method:
                   attr = getattr(self, key, None)
                   if not attr:
                          attr = getattr(self, underKey, None)
                          if not attr:
                                 if default!=_NoDefault:
                                       return default
                                  else:
                                       raise NamedValueError, key
         if method:
              return method(self)
         if attr:
              return attr

