Lambda going out of fashion

rzed jello at comics.com
Thu Dec 23 15:32:35 EST 2004


Jp Calderone <exarkun at divmod.com> wrote in
news:mailman.8345.1103812628.5135.python-list at python.org: 

> On Thu, 23 Dec 2004 13:36:08 GMT, rzed <jello at comics.com> wrote:
>>Stephen Thorne <stephen.thorne at gmail.com> wrote in
>> news:mailman.8299.1103775211.5135.python-list at python.org: 
>> > [snip]
>> > 
>> > {
>> >  'one': lambda x:x.blat(),
>> >  'two': lambda x:x.blah(),
>> > }.get(someValue, lambda x:0)(someOtherValue)
>> > 
>> > The alternatives to this, reletively simple pattern, which is
>> > a rough parallel to the 'switch' statement in C, involve
>> > creating named functions, and remove the code from the
>> > context it is to be called from (my major gripe).
>> >
>> > [snip]
>> 
>> Not addressing lambdas per se, but something similar to your
>> pseudo- switch statement can be done without using them at all.
>> One way might be to use a function dictionary wrapped in an
>> accessor function, such as this:
>> 
>> def dofns(key):
>>     fd2 = {
>>     0:'print "Key 0"',
>>     1:'print "one"',
>>     4:"\n".join(['for ix in range(15):',
>>                   '  print "%s%d" % (" "*ix,ix)']),
>>     }
>>     try:
>>         exec(fd2[key])
>>     except KeyError:
>>         print 'Key',key,'not found'
>> 
> 
>   I hate to be nasty, but *ugh* what a horrible way to start the
>   day. 
> 
>   There are so many things wrong with this.
> 
>   By exec'ing code strings you lose compile-time _syntax_ 
> checking.  I'm all for dynamicism, but it really is nice to let
> the compiler do _something_ things for you.
> 
>   By exec'ing code strings you slow down the entire function 
> by forcing a slower name-lookup code path in the interpreter.
> 
>   By exec'ing code strings you lose the ability to pass values 
> back to your caller (oh, you could "return" in one of those, but
> *ugg* that'd be even more terrible, and probably not what you
> want in most cases, since it doesn't let you get at the value
> except from your caller.  you could also set names in the local
> namespace but that's pretty messed up too, python already has a
> function return convention, making up your own is no fun).

Thanks for your comments. I'll not argue that I would actually put 
exactly this code into anything I intended for public consumption; 
it was to illustrate that there were in fact alternatives to 
lambda. 

In point of fact, though, there might be reasons to do something 
similar (addressing at least a couple of your objections). I don't 
think speed of execution is going to be a factor unless the main 
processing in the program centers on this snippet. It's a way to 
dummy up a switch statement, and while that could mean it was 
central to the program, it seems to me more likely to be relatively 
peripheral. 

In a switching application, the dynamic code shown would more 
likely be function invocations, but it could on occasion be useful 
to implement a script processor (I've used them for various 
reasons). Generally they seem most useful for interacting with 
humans (and hence with human speed limitations). 

One class of applications where such a technique could be useful 
would be in allowing various groups to access a database and 
perform operations on the data specific to their function. Dynamic 
searches, for instance, ad hoc reporting and the like. Not all 
groups would have the same needs or privileges, and using separate 
function tables is one way to limit activities to a specified 
range. 

It's fairly trivial to allow passing and returning data; the main 
difficulty (apart from security concerns) is choosing the 
convention to use. 

> 
>   There are probably more reasons this is bad too.
> 
>   Even using `def' to define a function for each of these would
>   be 
> preferable.
> 
>   Aside from that, exec() isn't a function.  You "exec foo", not
> "exec(foo)".  The latter works simply because parens act as to
> set precedent instead of as part of function call syntax when
> used this way.
> 
>   Also, you should do the dictionary lookup first, in a
>   try/except, 
> and then execute it later, _outside_ the try/except, otherwise
> you risk masking KeyErrors from exec'd code.
> 
>   Jp
> 

Good points, which I'll take to heart when I'm putting this stuff 
into production code. 
-- 
rzed




More information about the Python-list mailing list