[Tutor] SEC: UNCLASSIFIED:-dynamic binding of functions

Michael P. Reilly arcege@shore.net
Tue, 21 Dec 1999 08:19:12 -0500 (EST)

> Hi,
> How do I add a function ("method"?) to a class on the fly?
> ie: the name and contents of the function is unknown at compile time,
> but needs to be built at runtime from various bits of information.
> Alternatively, is there a way to run function foo at compile time to
> do the same thing? This is more than just macro expansion.
> (Probably not, but ... )

Everything in Python is dynamic, even module compilation is at runtime
(the byte-code is cached to the .pyc for later import, but still... ;).

Function definitions are statements, and so are class definitions. You
can construct new ones and then evaluate them at runtime:

>>> def make_multiplier(func_name, howmany, namespace):
...   # template for a function, whitespace is important
...   funcdef = '''\
... def %(func_name)s (x):
...   return %(howmany)d * x
... ''' % locals
...   exec funcdef in namespace
>>> make_multiplier('times_two', 2, globals()
>>> print times_two(4)

This creates functions, but functions are different from unbound
methods.  I'll leave that as an exercise, but a hint: classes are
namespaces too.

Then you can call this new method with:
>>> spam = Food()
>>> method = getattr(spam, 'times_two')
>>> result = method(3)

> [This is needed for serious syntactic sugar to avoid the need for
> 10-50 lines per affected class (I can't just subclass since the
> needed functions are slightly different for each affected class)
> where 1 line would do; it'll be run-once for each affected class
> and I'm willing to have a small speed hit as part of the startup
> cost]

It's likely that you can still handle the problem with subclassing.
Think about what operations are different for the different data, have
a generic function do that in the algorithm, then let the subclass
override the function.  But I won't dispute that it might be easier
with a little syntax sugar, but there may be another as easy way.
Sometimes it helps to put it away for a little while. :)

Good luck,

| Michael P. Reilly, Release Engineer | Email: arcege@shore.net        |
| Salem, Mass. USA  01970             |                                |