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