"Updating" lambda functions
Bengt Richter
bokr at oz.net
Thu Sep 16 16:58:58 EDT 2004
On 16 Sep 2004 14:07:20 GMT, Oliver Fromme <olli at haluter.fromme.com> wrote:
>Hi,
>
>I'm trying to write a Python function that parses
>an expression and builds a function tree from it
>(recursively).
>
>During parsing, lambda functions for the the terms
>and sub-expressions are constructed on the fly.
>Now my problem is lazy evaluation. Or at least I
>think it is. :-)
>
>I need to "update" a lambda function, like this:
>
> fu = lambda x: x
> ...
> fu = lambda x: fu(x) + 17
> ...
> fu = lambda x: fu(x) * 3
>
>Of course that doesn't work, because fu is resolved
>when the lambda is called, not when it's defined, so
>I'll run into an endless recursion.
>
>My current solution is to define a helper function
>which passes the lambda through its argument:
>
> def add_17 (fu):
> return lambda x: fu(x) + 17
>
> def mul_3 (fu):
> return lambda x: fu(x) * 3
>
> fu = lambda x: x
> ...
> fu = add_17(fu)
> ...
> fu = mul_3(fu)
>
>That works, but it strikes me as unclean and ugly.
>Is there a better way to do it?
>
>Best regards
> Oliver
>
>--
>Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany
>
>``All that we see or seem is just a dream within a dream.''
>(E. A. Poe)
You could exploit the way functions become bound methods, e.g.,
>>> fu = lambda x: x
>>> fu = (lambda f,x: f(x) + 17).__get__(fu)
>>> fu = (lambda f,x: f(x) * 3).__get__(fu)
>>> fu(1)
54
>>> fu(0)
51
>>> fu(-15)
6
>>> fu(-16)
3
>>> fu(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: <lambda>() takes exactly 2 arguments (3 given)
>>> fu
<bound method ?.<lambda> of <bound method ?.<lambda> of <function <lambda> at 0x008FD8B0>>>
or, you could make a magic function-composing object with magic composing properties,
exploiting the method-making mechanism in a different way, e.g.,
>>> class FC(object):
... def __setattr__(self, name, f):
... if not hasattr(self, name): self.__dict__[name] = [f]
... else: self.__dict__[name].append(f)
... def __getattribute__(self, name):
... if name == '__dict__': return object.__getattribute__(self, '__dict__')
... return type(self).__dict__['_xfuns'].__get__(
... object.__getattribute__(self,name))
... def _xfuns(flist, x):
... for f in flist: x = f(x)
... return x
...
>>> fc = FC()
>>> fc.fu = lambda x: x
>>> fc.fu = lambda x: x + 17
>>> fc.fu = lambda x: x * 3
>>> fc.fu(1)
54
>>> fc.fu(0)
51
>>> fc.fu(-15)
6
>>> fc.fu(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: _xfuns() takes exactly 2 arguments (3 given)
>>> fc.bar = lambda x: x*3
>>> fc.bar = lambda x: x+10
>>> fc.bar(0)
10
>>> fc.bar(2)
16
>>> fc.fu(-18)
-3
All just to explore python's features, not to recommend specific uses ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list