[Python-ideas] Multi Statement Lambdas

Terry Reedy tjreedy at udel.edu
Sun Oct 21 19:16:02 EDT 2018


On 10/21/2018 12:28 PM, Andreas Winschu wrote

> A def function has to be named.

In general, this is a good thing.  It often improves tracebacks. 
Perhaps more importantly, name facilitate testing and mocking.

> Wheres a lambda expression can be passed anonymously to any other 
> function as an argument.

Except for relatively trivial expressions, this is a bad thing.  All 
functions created from lambda expressions get the same pseudo-name 
'<lambda>'.  This can make tracebacks worse.  Perhaps more importantly, 
proper testing may become harder.

> /map(lambda x: x**2, array)/

It is obvious what this trivial expression does, but without a name or 
comment or context indicating intent, how do I know that it is correct? 
Trivial examples evade the issues that arise even with multiline 
expressions, let alone multiple statements.

 >>> for i in map(lambda x: x **
	 	 2, 'abc'):
	print(i)

Traceback (most recent call last):
   File "<pyshell#19>", line 2, in <module>
     2, 'abc'):
   File "<pyshell#19>", line 2, in <lambda>
     2, 'abc'):
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

> vs
> /def powers2(x)/
> /   x**2/
> /map(powers2, array)/

 >>> def pow2(x):
	return (x **
		2)

 >>> for i in map(pow2, 'abc'): print(i)

Traceback (most recent call last):
   File "<pyshell#26>", line 1, in <module>
     for i in map(pow2, 'abc'): print(i)
   File "<pyshell#24>", line 3, in pow2
     2)
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

Given that there might be a hundred functions named '<lambda>', I think 
the specific name is a bit helpful.

> Coming up with a name here is not needed, as the operation is expressive 
> enough.

It is clear as to the meaning.  And testing that pow2(3) equals 9 is 
pretty useless.  But you are proposing something else: adding anonymous 
multiple statement functions, where a name *and testing* is usually 
needed.  Justification for what we have today is not justification for a 
major change.

tkinter uses callbacks with widget commands and scheduling.  idlelib has 
77 matches for the re '[( ,]command='.  47 are followed by 
'self.somemethod'; 26 by other function names, and 4 by lambda 
expressions.  All four of the latter are trivial calls of a named 
method: self.somemethod(value).  So when all named non-test functions 
are tested, all non-test callbacks will be tested.

In spite of newbie problems with lambda, I am happy to not have to 
define trivial test functions like this.

     def undoNone(): return d.undo_event(None)

But doubt that I would rather write any of the independent 
production-code functions and methods as anonymous lambda constructs.

-- 
Terry Jan Reedy




More information about the Python-ideas mailing list