Velocity Reviews > how to convert a multiline string to an anonymous function?

# how to convert a multiline string to an anonymous function?

Danny Shevitz
Guest
Posts: n/a

 04-29-2008
Simple question here:

I have a multiline string representing the body of a function. I have control
over the string, so I can use either of the following:

str = '''
print state
return True
'''

str = '''
def f(state):
print state
return True
'''

and I want to convert this into the function:

def f(state):
print state
return True

but return an anonmyous version of it, a la 'return f' so I can assign it
independently. The body is multiline so lambda doesn't work.

I sort of need something like:

def function_constructor(str):
f = eval(str) # What should this be
return f

functions = {}
for node in nodes:
function[node] = function_constructor(node.text)

I'm getting stuck because 'def' doesn't seem to work in an eval function,
and exec actually modifies the namespace, so I run into collisions if I use
the function more than once.

I know I'm missing something stupid here, but I'm stuck just the same...

thanks,
Danny

Diez B. Roggisch
Guest
Posts: n/a

 04-29-2008
Danny Shevitz schrieb:
> Simple question here:
>
> I have a multiline string representing the body of a function. I have control
> over the string, so I can use either of the following:
>
> str = '''
> print state
> return True
> '''
>
> str = '''
> def f(state):
> print state
> return True
> '''
>
> and I want to convert this into the function:
>
> def f(state):
> print state
> return True
>
> but return an anonmyous version of it, a la 'return f' so I can assign it
> independently. The body is multiline so lambda doesn't work.
>
> I sort of need something like:
>
> def function_constructor(str):
> f = eval(str) # What should this be
> return f
>
> functions = {}
> for node in nodes:
> function[node] = function_constructor(node.text)
>
> I'm getting stuck because 'def' doesn't seem to work in an eval function,
> and exec actually modifies the namespace, so I run into collisions if I use
> the function more than once.
>
> I know I'm missing something stupid here, but I'm stuck just the same...

The "stupid" thing is that you can pass your own dictionary as globals
to exec. Then you can get a reference to the function under the name "f"
in the globals, and store that under whatever name you need.

Beware of recursion though! If that happens, you need to create unique
names for your functions, but as you know these beforehand I don't see
any problem with that - just enumerate them, like f1, f2, f3....

Diez

Matimus
Guest
Posts: n/a

 04-30-2008
On Apr 29, 3:39 pm, "Diez B. Roggisch" <(E-Mail Removed)> wrote:
> Danny Shevitz schrieb:
>
>
>
> > Simple question here:

>
> > I have a multiline string representing the body of a function. I have control
> > over the string, so I can use either of the following:

>
> > str = '''
> > print state
> > return True
> > '''

>
> > str = '''
> > def f(state):
> > print state
> > return True
> > '''

>
> > and I want to convert this into the function:

>
> > def f(state):
> > print state
> > return True

>
> > but return an anonmyous version of it, a la 'return f' so I can assign it
> > independently. The body is multiline so lambda doesn't work.

>
> > I sort of need something like:

>
> > def function_constructor(str):
> > f = eval(str) # What should this be
> > return f

>
> > functions = {}
> > for node in nodes:
> > function[node] = function_constructor(node.text)

>
> > I'm getting stuck because 'def' doesn't seem to work in an eval function,
> > and exec actually modifies the namespace, so I run into collisions if I use
> > the function more than once.

>
> > I know I'm missing something stupid here, but I'm stuck just the same...

>
> The "stupid" thing is that you can pass your own dictionary as globals
> to exec. Then you can get a reference to the function under the name "f"
> in the globals, and store that under whatever name you need.
>
> Beware of recursion though! If that happens, you need to create unique
> names for your functions, but as you know these beforehand I don't see
> any problem with that - just enumerate them, like f1, f2, f3....
>
> Diez

In other words:

>>> d = {}
>>>
>>> # don't use str, that is the name of the built-in string type
>>> text = '''

.... def f(state):
.... print state
.... return True
.... '''
>>>
>>> exec text in d
>>>
>>> f('state')

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined
>>>
>>> f = d['f']
>>> f('state')

state
True

Matt

Danny Shevitz
Guest
Posts: n/a

 04-30-2008
Thanks All!

you've solved my problem.

D