Weird lambda rebinding/reassignment without me doing it
steve at REMOVE-THIS-cybersource.com.au
Sat Jul 12 17:40:33 CEST 2008
On Thu, 10 Jul 2008 14:09:16 -0400, Terry Reedy wrote:
>>>>>> g = lambda x:validate(x)
> This is doubly diseased.
> First, never write a 'name = lambda...' statement since it is equivalent
> to a def statement except that the resulting function object lacks a
> proper .funcname attribute.
Using lambda in this way is no more "diseased" than aliasing any other
object. It's a matter of personal preference not to bind a lambda to a
name. Functions, whether created by lambda or def, are first class
objects, and as such there's nothing wrong with binding them to names.
Admittedly, the lack of a func_name attribute can sometimes make
tracebacks harder to understand, especially if you've got many bound
lambdas. But that's no worse than this:
>>> def factory(n):
... def f():
... return "spam"*n
... return f
>>> one_spam = factory(1)
>>> two_spam = factory(2)
>>> one_spam.func_name == two_spam.func_name
I'm sure that nobody would argue that using factory functions is
"diseased" because the functions have the same func_name attribute --
even if it does sometimes make it harder to interpret tracebacks:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes no arguments (1 given)
So by all means say that you personally don't like to bind lambdas to
names, but don't pretend that it is somehow wrong to do so.
> Second, never write a function (with either def or lambda) that simply
> returns a function of the argument(s).
I think you need to reconsider the way you say that. By definition,
*every* function simply returns a function of the arguments. That's what
> The wrapping does nothing! This
> is a waste of time and space for both you and the interpreter.
When I was a newbie, I used to write:
That was before I learned to just do this:
sin = math.sin
But just to prove that you should never say never:
>>> import timeit
>>> T1 = timeit.Timer("f(1)", """def g(x):
... return x+1
... f = g
>>> T2 = timeit.Timer("f(1)", """def g(x):
... return x+1
... def f(x):
... return g(x)
[0.50848197937011719, 0.54573416709899902, 0.54767107963562012]
[0.88546991348266602, 0.89811587333679199, 0.95785093307495117]
So that's a good reason to wrap a function in another function -- to
measure the overhead of a function call.
More information about the Python-list