7

I would like to do something like the following:

def getFunction(params):
   f= lambda x:
       do stuff with params and x
   return f

I get invalid syntax on this. What is the Pythonic/correct way to do it?

This way I can call f(x) without having to call f(x,params) which is a little more messy IMO.

Maroun
  • 94,125
  • 30
  • 188
  • 241
user3391229
  • 798
  • 9
  • 17

3 Answers3

10

A lambda expression is a very limited way of creating a function, you can't have multiple lines/expressions (per the tutorial, "They are syntactically restricted to a single expression"). However, you can nest standard function definitions:

def getFunction(params):
   def to_return(x):
       # do stuff with params and x
   return to_return

Functions are first-class objects in Python, so once defined you can pass to_return around exactly as you can with a function created using lambda, and either way they get access to the "closure" variables (see e.g. Why aren't python nested functions called closures?).

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    The key point is a `def`'d function is just a first-class value itself, like the result of the lambda, with the same "closure" access. – user2864740 Feb 04 '15 at 15:54
6

It looks like what you're actually trying to do is partial function application, for which functools provides a solution. For example, if you have a function multiply():

def multiply(a, b):
    return a * b

... then you can create a double() function1 with one of the arguments pre-filled like this:

from functools import partial

double = partial(multiply, 2)

... which works as expected:

>>> double(7)
14

1 Technically a partial object, not a function, but it behaves in the same way.

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • Cool. Can you comment on when this library would have use over a solution like johnrsharpe posted above? – user3391229 Feb 04 '15 at 23:31
  • 1
    @user3391229 If you want a partial function (as above), use `partial()` - it's less verbose and you're less likely to make a mistake. If you need something more complex, use a closure as in Jon Sharpe's answer. This is an instance of a general rule of thumb in Python - if the included batteries solve your problem, use them. – Zero Piraeus Feb 05 '15 at 00:03
2

You can't have a multiline lambda expression in Python, but you can return a lambda or a full function:

def get_function1(x):
    f = lambda y: x + y
    return f

def get_function2(x):
    def f(y):
        return x + y
    return f
famousgarkin
  • 13,687
  • 5
  • 58
  • 74