predicate classes

Neel Krishnaswami neelk at brick.cswv.com
Tue Nov 30 20:56:47 EST 1999


Justus Pendleton <justus at my-deja.com> wrote:
>I decided to broaden my horizons so I was reading about/playing around with
>Cecil.	One of the things Cecil has that I hadn't heard of before are
>predicate classes:
>
>(http://www.cs.washington.edu/research/projects/cecil/cecil/www/www/Papers/
> predicate-classes.html), which I thought were nifty beyond all belief.

Good for you! I like Cecil a lot, too. You might also be interested in
Self (http://self.sunlabs.com) -- it implements dynamic inheritance,
which is one of the motivations for Chambers' invention of predicate
classes.

>I also thought it would be nifty if Python had them so I got the source
>from the CVS respository and started hacking the grammar and realized I
>had no idea what I was doing :-).
>
>Before getting in any deeper in something I only vaguely understand I
>thought I would ask the opinions of people who know more about Python
>than I whether they think it would be easy/hard/well-damn-nigh-impossible 
>to add this kind of dynamic retyping of objects based on predicates.

Fortunately, you don't need to hack the Python source in order to
experiment with dynamic inheritance or predicate classes in Python,
because you can change a class's inheritance tree by assigning to a
class's __bases__ attribute at runtime.

Here's a quick, rather kludged-together example:

class Foo:
    x = 4

class Bar:
    predicate = 1
    __bases__ = (Foo,)
    #
    def __setattr__(self, name, value):
        if name == 'predicate':
            self.__class__.predicate = value
            if value:
                self.__class__.__bases__ = (Foo,)
            else:
                self.__class__.__bases__ = ()

At the interpreter prompt:

>>> s = Bar()
>>> isinstance(s, Foo)
1
>>> s.x
4
>>> s.predicate = 0
>>> isinstance(s, Foo)
0
>>> s.x
Traceback (innermost last):
  File "<stdin>", line 1, in ?
AttributeError: x

Whether or not s, the instance of Bar, inherited from Foo depends 
on what the value of Bar.predicate was. Note that this isn't the 
same thing  as real predicate dispatch, yet, since different 
instances of Foo can't have different virtual classes. 

To make that work, you would need to create a custom sequence object
for your __bases__ object and hack together a metaclass to install it
cleanly. This isn't a simple project, but fortunately, it's not a big
job either -- most of the work is conceptual rather than writing reams
of code.

It will also be lots of fun; my current Python project right now is
writing a multimethod class for Python and I can vouch for the hack
value of something like this.

Some day in the future, *after* you have a good idea of what semantics
you want to implement, you can create a C extension type implementing
predicate classes and then extend the interpreter. But that's for
later; first prototype it in Python itself before wasting time writing
C code. Remember you won't know what the right thing is until you've
used your metaclass in a variety of projects, and you will feel much
easier about modifying and rewriting a Python class than a C
extension.

>(I did a quick search on deja and didn't find any talk about this, so
>apologies in advance if this is something that has been as talked to
>death as the indentation thing.)

Not at all! Cecil, Dylan and Self are all great languages to use to
discover Pythonic features in. :)


Neel




More information about the Python-list mailing list