Creating a function object from a string

Narcolapser picture Narcolapser · May 23, 2011 · Viewed 15.1k times · Source

Question: Is there a way to make a function object in python using strings?


Info: I'm working on a project which I store data in a sqlite3 server backend. nothing to crazy about that. a DAL class is very commonly done through code generation because the code is so incredibly mundane. But that gave me an idea. In python when a attribute is not found, if you define the function __getattr__ it will call that before it errors. so the way I figure it, through a parser and a logic tree I could dynamically generate the code I need on its first call, then save the function object as a local attrib. for example:

DAL.getAll()

#getAll() not found, call __getattr__

DAL.__getattr__(self,attrib)#in this case attrib = getAll

##parser logic magic takes place here and I end up with a string for a new function

##convert string to function

DAL.getAll = newFunc

return newFunc

I've tried the compile function, but exec, and eval are far from satisfactory in terms of being able to accomplish this kind of feat. I need something that will allow multiple lines of function. Is there another way to do this besides those to that doesn't involve writing the it to disk? Again I'm trying to make a function object dynamically.

P.S.: Yes, I know this has horrible security and stability problems. yes, I know this is a horribly in-efficient way of doing this. do I care? no. this is a proof of concept. "Can python do this? Can it dynamically create a function object?" is what I want to know, not some superior alternative. (though feel free to tack on superior alternatives after you've answered the question at hand)

Answer

Gurgeh picture Gurgeh · May 23, 2011

The following puts the symbols that you define in your string in the dictionary d:

d = {}
exec "def f(x): return x" in d

Now d['f'] is a function object. If you want to use variables from your program in the code in your string, you can send this via d:

d = {'a':7}
exec "def f(x): return x + a" in d

Now d['f'] is a function object that is dynamically bound to d['a']. When you change d['a'], you change the output of d['f']().