On 12 Dec 2005 21:38:23 -0800, "Jacob Rael" <[EMAIL PROTECTED]> wrote:
>Hello,
>
>I would like write a function that I can pass an expression and a
>dictionary with values. The function would return a function that
>evaluates the expression on an input. For example:
>
>fun = genFun("A*x+off", {'A': 3.0, 'off': -0.5, 'Max': 2.0, 'Min':
>-2.0} )
>
>>>> fun(0)
>-0.5
>>>> fun(-10)
>-2
>>>> fun(10)
>2
>
>so fun would act as if I did:
>
>def fun(x):
> A = 3
> off = -0.5
> Max = 2
> Min = -2
> y = min(Max,max(Min,A*x + off))
> return(y)
>
>Any ideas?
ISTM genFun above can't generate fun without special interpretation
of Min and Max. I.e., how is it supposed to know to use min and max (lower case)
as in your expression for y, unless you tell it to by writing
fun = genFun("min(Max,max(Min,A*x+off))", {'A': 3.0, 'off': -0.5, 'Max':
2.0, 'Min':
or state a rule about using min and/or max when Max and/or Min are present?
Setting aside security for the moment, and guessing at the rule you might
want for Min and Max, perhaps something like (untested beyond what you see):
(also limited to using x as the single function parameter name in the
expression!)
>>> import math
>>> allow = dict((k,v) for k,v in vars(math).items()
... if callable(v) and not k.startswith('_') or k in
('e','pi'))
>>>
>>> allow.update(min=min, max=max)
>>> def vetexpr(expr, dct): return expr # XXX generate and check AST later
...
>>> def genFun(expr, dct=None):
... d = allow.copy()
... if dct: d.update(dct)
... expr = '('+expr+')'
... vetexpr(expr, d) # check for illegal stuff XXX later
... if 'Min' in d: expr = 'max(Min, %s)'%(expr,)
... if 'Max' in d: expr = 'min(Max, %s)'%(expr,)
... return eval('lambda x: %s'%expr, d)
...
>>> fun = genFun("A*x+off", {'A': 3.0, 'off': -0.5, 'Max': 2.0, 'Min': -2.0})
>>> fun
<function <lambda> at 0x02EEBDF4>
>>> fun(0)
-0.5
>>> fun(-10)
-2.0
>>> fun(10)
2.0
>>> import dis
>>> dis.dis(fun)
1 0 LOAD_GLOBAL 0 (min)
3 LOAD_GLOBAL 1 (Max)
6 LOAD_GLOBAL 2 (max)
9 LOAD_GLOBAL 3 (Min)
12 LOAD_GLOBAL 4 (A)
15 LOAD_FAST 0 (x)
18 BINARY_MULTIPLY
19 LOAD_GLOBAL 6 (off)
22 BINARY_ADD
23 CALL_FUNCTION 2
26 CALL_FUNCTION 2
29 RETURN_VALUE
I just made things from the math module accessible in anticipation. E.g.,
>>> sin2xd = genFun('sin(2.0*x*pi/180.)')
>>> sin2xd(15)
0.49999999999999994
>>> sin2xd(0)
0.0
>>> sin2xd(45)
1.0
Of course, if the dict is all constant named coefficients, you could substitute
them as
literal values in the expression before generating the function. You could do
that
in the placeholder vetexpr, but we'll leave that implementation for another
post ;-)
Regards,
Bengt Richter
--
http://mail.python.org/mailman/listinfo/python-list