Why anonymity? [was Re: map/filter/reduce/lambda opinions and background unscientific mini-survey]

Steven D'Aprano steve at REMOVETHIScyber.com.au
Thu Jul 7 11:45:34 EDT 2005


On Thu, 07 Jul 2005 09:36:24 +0000, Duncan Booth wrote:

> Steven D'Aprano wrote:
>> This is something I've never understood. Why is it bad 
>> form to assign an "anonymous function" (an object) to a 
>> name?
> 
> Because it obfuscates your code for no benefit. You should avoid making it 
> hard for others to read your code (and 'others' includes yourself in the 
> future).

I don't particularly think I'm that much smarter than the average
programmer. In fact I *know* that I'm not that much smarter. So why do I
see nothing obfuscated or obscure or difficult to understand in func =
lambda x: x**3 - 5*x when apparently most of the Python community find it
too complicated?

Whichever is "more readable" in the absolute sense, the "abused" lambda
expression above is within a gnat's whisker of the def equivalent,

def func(x):
    return x**3 - 5*x

I honestly don't understand why it is supposed to be so hard to follow.

I can think of many function which should not be written with lambda, just
as some things shouldn't be written as list comps. But within the limits
of how much complexity you can reasonably include in a single expression,
I don't see why lambda puts people off.

I make it, eight mental tokens (not necessarily the same as Python tokens)
for the lambda versus nine for the def. A trivial difference. In my mind,
the tokens are:

func, =, lambda, x, :, x**3, -, 5*x

compared to:

def, func, (), x, :, return, x**3, -, 5*x

(Your mental parser may differ.)


> Also, it obfuscates tracebacks: all lambda expressions will identify in 
> tracebacks as <lambda>, but if you define a function you can give it a 
> meaningful name.

Well there is that. If you have lots of lambdas assigned to names, I guess
debugging could be more difficult:

py> f = lambda x: 1.0/x
py> f(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 1, in <lambda>
ZeroDivisionError: float division


py> def f(x):
...     return 1.0/x
...
>>> f(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in f
ZeroDivisionError: float division

So far so good. But then:

py> g = f
py> del f
py> g(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in f
ZeroDivisionError: float division

(but we actually got the error by calling g, not f, and in fact f no
longer exists at the point we called g)


>> Why is it considered abuse of lambda to assign the 
>> functions to a name? Is it an abuse of lambda to do this?
>> 
>> D = {"one": lambda noun: noun,
>>      "two": lambda noun: noun + 's',
>>      "many": lambda noun: 'lots of ' + noun + 's' }
>> 
>> assert D["two"]("python") == "pythons"
>> 
>> 
> No, that is approaching a reasonable use of lambda, however I would still 
> be inclined to write it with functions. e.g.
> 
>    def one(noun):
>        return noun
> 
>    def two(noun):
>        return noun+'s'
> 
>    def many(noun):
>        return 'lots of %ss' % (noun,)
> 
>    D = dict(one=one, two=two, many=many)

I find your version far more difficult to follow than mine.

Psychologically, I find that defs seem to carry significant mental weight
in a way that lambdas don't. Even though the lambda forms are
equivalent to the def forms, I find that the defs are more heavy-weight in
my conceptual map of the program than a lambda would be.

Put it this way: whenever I see a two-line def as above, I can't help
feeling that it is a waste of a def. ("Somebody went to all the trouble
to define a function for *that*?") Yet I would never think the same about
a lambda -- lambdas just feel like they should be light-weight. 

Am I just weird?



-- 
Steven.





More information about the Python-list mailing list