Class introspection and dynamically determining function arguments

Mike C. Fletcher mcfletch at rogers.com
Sat Jan 22 13:44:06 EST 2005


Bengt Richter wrote:

>On Fri, 21 Jan 2005 20:23:58 -0500, "Mike C. Fletcher" <mcfletch at rogers.com> wrote:
>
>  
>
>>>On Thu, 20 Jan 2005 11:24:12 -0000, "Mark English" <Mark.English at liffe.com> wrote:
>>>      
>>>
...

>Does the BasicProperty base class effectively register itself as an observer
>of subclass properties and automatically update widgets etc., a la Delphi
>data-driven visual components? I've thought of doing a light-weight form
>extension class that would use a text (maybe CSV) definition to control
>contruction, and easy programmatic manipulation by python of the definition
>parameters, like a stripped-down version of the text view of Delphi forms.
>It could also be done via Tkinter, to prototype it. It would be interesting
>to allow dragging widgets and edges around in Tkinter and round-trip the parameter
>changes automatically into the text representation. A little (well, ok, a fair amount ;-)
>further and you'd have a drag-n-drop GUI design tool. But don't hold your breath ;-)
>  
>
BasicProperty itself doesn't register as an observable/observer, 
BasicProperty is the lowest-level of the software stack, so it allows 
you to override and provide notification (e.g. using PyDispatcher) on 
property-setting.  ConflictSolver (old project to create a room 
scheduler) used that to do automatic updating of widgets in the wxPython 
UI based on Model changes (though I don't remember if it was 
per-property or per-object).  My goal for the wxoo project was to 
provide hooks in the wxPython GUI designers for dropping in property 
sheets and/or property-aware controls such that you would have the 
equivalent of "data aware" controls in VB or Access (keeping in mind 
that BasicProperty properties can also represent fields in database rows).

Aside:

    The VRML97 field class in OpenGLContext does notifications for every
    set (using PyDispatcher), btw.  It's a little more limited in its
    scope (focus on 3D data-types), but the effect is what allows the
    scenegraph to cache and then rebuild its internal rendering
    structures with very low overhead.

...

>>Anyway, if you aren't interested in BasicProperty for this task; another 
>>project on which I work, PyDispatcher provides fairly robust mechanism 
>>(called robustApply) for providing a set of possible arguments and using 
>>inspect to pick out which names match the parameters for a function in 
>>order to pass them in to the function/method/callable object.  That 
>>said, doing this for __init__'s with attribute values from an object's 
>>dictionary doesn't really seem like the proper way to approach the problem.
>>    
>>
>Sounds like a workaround for parameter passing that maybe should have been
>keyword-based?
>  
>
Not as such, that is, not a workaround, and it shouldn't be keyword 
based ;) .

The problem with using keyword-based passing is that every method needs 
to be written with this awareness of the keyword-handling structures.  
You spread pointless implementation details throughout your codebase.  
PyDispatcher lets you write very natural functions for dealing with 
events without having every function use **named parameters.

I've now written quite a few such systems, and I'm currently balanced 
between two approaches; that taken in PyDispatcher (define only natural 
parameters, have the system figure out how to deliver them to you), and 
that taken in OpenGLContext (define an event-class hierarchy which 
encapsulates all information about the events).

The PyDispatcher approach is nice in that it makes simple things very 
simple.  You want access to the "lastValue" parameter in the 
"environment" of the event and nothing else, you define your function 
like so:

    def handler( lastValue ):
        print 'got last value', lastValue

which works very nicely when you're early in the development of a 
system, or are linking multiple systems.  There's no need to do all 
sorts of extra work defining event hierarchies, you can often leave 
given handlers entirely alone during refactoring if they aren't dealing 
with the changed properties in the event-environment.

The OpenGLContext approach is more appropriate when you have a large 
system (such as OpenGLContext), where defining an event class is a 
trivial task compared to the total system expenditure.  It allows for 
such things as putting methods on the event objects to make debugging 
easy, and providing common functionality.  It starts to show it's worth 
when you start needing to reason about the phenomena of events 
themselves, rather than just about the phenomena the events represent 
(e.g. when you need to cache, delay, or reorder events).

The named argument passing approach has the disadvantage that every 
function must be written with knowledge of that use of named arguments:

    def handler( lastValue, **named ):
        print 'got last value', lastValue

when using such systems in the past I've often wound up with errors deep 
in an application where some seldom-called callback didn't have a 
**named parameter, so the system would abort (well, log an error) trying 
to call it.

Is it a huge overhead? No.  But its unnecessary if you've got a tool 
that takes care of that "implementation-level" detail for you.  Compared 
to robustApply, the difference is pretty minimal.  If you define a 
**named parameter, for instance, you will get the remainder of the 
robustApply environment passed in.

In another lifetime, you could imagine these systems being written as 
wrappers that added a nested scope around the definition of the function 
such that the scope forwarded unresolved name references to the 
environment of the event (non-lexical scoping), but that would lack the 
explicitness of passing in the arguments from the environment and would, 
I suppose be evil in a quite non-trivial way.

Peace, and have fun,
Mike

________________________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://www.vrplumber.com
  http://blog.vrplumber.com




More information about the Python-list mailing list