convert string to a method of a class at runtime?
Kragen Sitaker
kragen at pobox.com
Sun Jun 2 22:18:07 EDT 2002
"Kevin Altis" <altis at semi-retired.com> writes:
> >>> s
> 'def world(self, s):\n print s\n\n'
> >>> c = compile(s, '', 'exec')
> >>> c
> <code object ? at 0164B620, file "", line 1>
Now 'c' is not the code object that is the body of 'world'; it is a
code object which, if executed, will create a function called 'world'.
> >>> import new
> >>> f = new.function(c, globals())
> >>> h.__class__.__dict__['world'] = new.instancemethod(f, None, h.__class__)
> >>> h.world('new world')
> Traceback (most recent call last):
> File "<input>", line 1, in ?
> TypeError: ?() takes no arguments (2 given)
And, not surprisingly, c takes no args.
> Fingers crossed, that this kind of dynamic method addition is doable.
For Q&D, you could probably get away with exec astring in globaldict,
aclass.__dict__.
This works for me in Python 2.1.1 and 1.5.2:
class MethodBroken(Exception): pass
def methodadd(astring, aclass, globaldict=globals()):
localdict = {}
exec astring in globaldict, localdict
methodnames = localdict.keys()
if len(methodnames) != 1:
raise MethodBroken("Method code didn't define exactly one method",
astring,
methodnames)
name = methodnames[0]
setattr(aclass, name, localdict[name])
I was surprised to learn not long ago that setattr() on class objects
will turn ordinary functions into instance methods for you.
> But I need to be able to do the addition outside the shell, so compiling the
> string is necessary.
exec will compile for you if you give it a string instead of a code
object. If you want, you can compile separately:
code = compile(astring, '', 'exec')
exec code in globaldict, localdict
That might give you better control over error handling, for example.
> In more complex examples, the method needs the namespace to be right
> so it can make use of whatever imports and other global variables
> have been setup.
Unfortunately, I don't think there's a way to extract the globals from
a class unless it has methods.
More information about the Python-list
mailing list