One Python 2.1 idea

Alex Martelli aleaxit at yahoo.com
Thu Jan 4 07:28:51 EST 2001


"Moshe Zadka" <moshez at zadka.site.co.il> wrote in message
news:mailman.978534843.948.python-list at python.org...
> [Moshe asks for problem where changing __class__ would be useful]

Actually, you asked more generally -- for problems in which
*transiently changing the behavior of a few methods of a few
objects* is the application-need.  I think it's meaningful
that you now phrase this as 'changing __class__' -- that's
just one WAY to 'change behavior', yet you think of them as
one and the same thing.  It's thus not surprising that you
conclude:

> I must say that in this case, I'm *sure* I'd fiddle with __class__
> rather then the new module. It's simple more obvious to write:

It's surely more obvious if one equates 'belongs to class X'
with 'has the behavior of class-X instances'... trivially true,
in fact.  But I thought the point of this sub-thread was
separating actual application-needs (transient behavior
changes in selected methods of certain objects: are they
ever really needed?) with ways to meet them (as I said, I
was _not_ using Python in that system, so neither changing
class nor transiently setting bound-methods was an option!-).


> > The simplest way to frame this, is to tell the plug-in authors
> > that they can just substitute their own code for any given
> > subset of methods of any exposed objects they can identify,
> > and 'restore' the original behavior when needed.
> [Ed. -- Other solution is to implement half of common lisp yourself]

It's not really that bad -- in fact, a full-fledged rich event
system is what we've used as the underlying framework for the
current version of our application, and it does work great (by
'rich' event-system, I have in mind one in which 'an event' is
incarnated into an event-object, just like in HMTL's DOM, rather
than being an insubstantial 'message' [function-call, etc], as
in most GUI's event-systems, COM events, etc).  Its generality
does make it somewhat harder to present; it's just easier for the
uninitiated to think of "A calls method B on object C", than of
"A instantiates eventobject E with E.request=B, E.target=C, then
posts E to the event-manager's queue (say, as a blocking-request
with high priority); C is among the listeners waiting for such
events [often, since the event-object has a specific target, the
_only_ listener, so the event-manager can be very speedy in its
delivery] -- when its turn comes to have a go at handling the
event, it runs whatever code is needed, sets E.response in the
appropriate way, and tells to the event-manager 'I've been quite
thorough in handling this event E, I don't think anybody else
needs to have a go at it' -- and the eventmanager finally
unblocks the waiting A, which can extract E.response and use it".

However, such typical use cases can and do get easily cast
into code -- it's just that the 'normal' call, in A's code:
    response = C.B()
becomes, in reality
    response = EventManager.PostMethodEvent(C, B)
where method MethodEvent of the EventManager handles the
above-mentioned semantic complexity (in fact, syntax can
be prettified back to the former case, if all possible
targets inherit from the appropriate mixin class that
knows how to direct stuff to the event-manager).

Similarly, 'hooking' the specific method B of the specific
object C is quite easy here -- C itself never even learns
about some of its methods being 'hooked' -- the 'hooker'
just asks _the event manager_ to install a listener on its
behalf, with priority just higher than C's listener, for
certain event patterns (those with target=C, request=B),
and basically "steals" the messages just before they actually
reach C itself.  Again, of course, this typical use case is
presented to plugin authors in encapsulated form, as easy
to use as 'temporarily changing C's own method B' would be.

Yeah, yeah, I know, nobody believes this can be as speedy
as it turns out to be without loss of generality, but, the
proof of the pudding being in the eating, I can but invite
interested parties to have a look at thinkdesign's new
release 6 (www.think3.com) -- all of the UI (G, speech, &c)
is based on the new 'rich event manager', as is some part of
the internals' object-model exposure.  The simplest caching
techniques in the event-manager turn out to be enough to
practically avoid overhead in the simple (and by far most
frequent) cases.  Who knows, maybe one day I'll be allowed
to opensource it (one of my fondest dreams)...!


Back to the general issues...: the kind of dynamism we're
considering here may not be really warranted in production
applications *unless* one needs a lot of dynamic, flexible
configurability in one's program (including 3rd-party
plug-ins, etc); however, I think that such 'needs' are
becoming more and more common.

The more dynamic things get, the less, I believe, a
purely class-based object model is appropriate -- but
that is a separate issue, related to HOW one meets such
needs, rather than to the facts that the needs emerge.

"Events rule" -- or, at least, that is my current opinion.
It _would_ be great if Python had better support for them,
at least on a par with Tcl's...


Alex






More information about the Python-list mailing list