Fuzzy thoughts / needs about class derivation / nesting

François Pinard pinard at iro.umontreal.ca
Sun Oct 31 17:55:52 EST 1999


Hi.  I guess it is better to share some quick fuzzy thoughts now, than
wait forever, or almost, before presenting a cathedralistic suggestion.

Python is the first language in which I feel comfortable enough to explore
OO concepts, which concepts I never liked so much before: I always found
the concepts a bit "buzzwordy", and usually easy to simulate by other means
in the languages I used.  Scheme was comfortable for exploring closures,
continuations (and laziness).  My only real use of continuations was to
implement backtracking matchers, and I did not have that need yet in Python.
I presume that threads could be used for the simplest cases of continuations,
but I'm not sure there is an easy Python paradigm for the ability of using
a given continuation more than once.

I did find closures often useful.  In Python, closures could be simulated
enough for my needs through function within instances, like in that piece
of code (much simplified):


def editor(*rules):
    return Editor(rules).proper

class Editor:

    def __init__(self, rules):
        self.rules = []
        for delete, insert in rules:
            self.rules.append((re.compile(delete), insert))
        # And other optimisations.

    def proper(self, lines):
        for counter in range(len(lines)):
            if not self.rules:
                break
            # Code to apply edition rules and remove them after match.
        return lines


I just call `editor' many times and save the returned function into various
lists, for later usage, after sorting and other massaging.  This is much
more heavy to write than in Scheme, it forces kind of over-documentation
of closures: but this is quite acceptable when we want to discipline usages.

We could somewhat simulate instantiated classes with functions in Scheme,
if we go functional all over, but it is less clear to me how we could
really implement classes, at least within a single evaluation environment.
There is a lot of relation between generic functions, closures, classes and
instances, and the expressibility of some concepts with the remaining others,
it will take a good while before everything becomes limpid in my mind :-).


On another topic, I recently missed much the capability of somewhat nesting
classes, instead of deriving them.  In Python, one overrides class functions,
and function nesting has to be artificially expressed.  Here is an excerpt
of an actual example, but it repeats dozens of times in my things, so far:


class Action:

    def __init__(self):
        # Some code to begin initialisation.

    def complete_init(self):
        # Some code to end initialisation.


class File_Action(Action):

    def __init__(self, name):
        Action.__init__(self)
        # Some code for more specific initialisation.


class Modify(File_Action):

    def __init__(self, name, filter, cleanup, install):
        File_Action.__init__(self, name)
        # Some code for even more specific initialisation.


class Copy(Modify):

    def __init__(self, source, name, install):
        Modify.__init__(self, name, None, None, install)
        # Some code for ultimate initialisation.
        self.complete_init()


Having to use `self.complete_init' in leaves classes, and not in intermediate
classes, is not very elegant.  I could provide dummy intermediates, but
would most probably eliminate them on sight when later rereading the code.
What I miss, here, is some kind of "inner" statement, like in Simula-67,
which has been copied in a few other languages since.  If I could write:


class Action:

    def __init__(self):
        # Some code to begin initialisation.
        inner
        # Some code to end initialisation.


and be done without defining or calling `self.complete_init', I would be
happier (whatever the syntax is).  The difficulty, of course, is that
it would break the pure override semantics of function definitions in
sub-classes.  Following what `ad-do-it' does for advice functions in Emacs,
it would also be fun if `inner' could be use more than once.  For example:


class Action:

    def __init__(self):
        # Some code to begin initialisation.
        try:
            inner
        except:
            # Some code to establish a more robust evaluation context.
            inner
        # Some code to end initialisation.


Of course, it would be nice if "inner" was also usable in intermediate
classes, and was a mere no-operation in leaves.  I hardly see, using
current Python paradigms, how one could express the above `try-except'
structures for nested initialisation in derived classes, without writing
code which would be quickly clumsy.  The best I can think of is splitting
many functions into a _first, _inner and _last components, with control
explicitly flowing back and forth between sub-classes and super-classes.
Not very neat.  It would be more fun if Guido could invent some elegant
and simpler structuring device addressing the real need behind the above
fuzzy suggestions.  Since we often see `Python 2.0' in subject threads in
this list, maybe the time is proper to try expressing such needs.

-- 
François Pinard   http://www.iro.umontreal.ca/~pinard






More information about the Python-list mailing list