Python multiline lambda

You can write it as an inline function:

lambda x, y : (x<=y)*(y-x) + (x>y)*x*y

You can define your lambda on multiple lines if you put the expression in parentheses. This creates an implied line continuation, causing newlines to be ignored up to the closing parenthesis.

>>> func = lambda a,b: (
...     b - a if a <= b else
...     a*b
... )
>>>
>>> func(23, 42)
19

You can also explicitly use the line continuation character "\", but this is not the approach preferred by the Python style guide. (Not that binding lambdas to names are a good idea to begin with, in fairness...)

>>> func = lambda a,b: \
...     b - a if a <= b else \
...     a*b
>>>
>>> func(23, 42)
19

Of course, you can only have expressions inside your lambda, and not statements. So proper if blocks and returns and the like are still impossible.


Additionally, it may not be necessary to use lambdas here at all, because unlike C# (prior to the recent v. 7.0), Python is capable of nesting full functions:

>>> def method(x,y):
...     def func(a,b):
...             if a <= b:
...                     return b - a
...             return a * b
...     return func(x,y)
...
>>> method(23, 42)
19

There is a tricky way of creating not just a multi-line lambda for formatting, but also one that is truly multi-line logically. It involves using the exec command to turn a string into a function. I don't know how efficient this is but it works. I came up with this because sometimes I want to create a custom lambda function for the sorted function and don't want to define a persistent function. So check out the following:

def strToFun(x):
    name = x[x.find(' ') + 1:x.find('(')]
    exec(x)
    ret = eval(name)
    return ret

This will create a function and return a pointer to that function. If you run the following test, you will see there is a function called f1 but not one called fun1. The fun1 is a placeholder because we have to have a function name when using def. exec creates a function inside the strToFun function. eval returns a pointer to that function without executing it. The function returns the pointer and the inner function called fun1 falls out of scope.

f1 = strToFun('def fun1(x): return x + 1')
print(f1, type(f1), f1(100))
print(dir())

Instead of storing the newly created function to a variable you could also just use it directly just like you would a lambda expression:

print(strToFun('def fun1(x): return x + 1')(200))

So I use it like this to create complex lambdas when I need to:

countries = ['Uganda', 'Canada', 'USA', 'Albania', 'USA']

print(sorted(countries
, key = strToFun(
'''def _fun1(x):
   if x == 'USA':
      return (0,)
   elif x == 'Canada':
      return (1,)
   else:
      return(2, x)
   ''')))

I am sure I will get a lot of comments about how unpythonic this is and that if Guido wanted us to have multi-line lambdas he would have put it in the language. Nevertheless, it is an interesting and effective trick when you need it, so what could be wrong with that?

Tags:

Python

C#

Lambda