alexnesov
alexnesov

Reputation: 135

What is the mechanism behind a function that contains a lambda expression? (Python)

During a tutorial I stumbled upon the following example. I get the general purpose and mechanism of functions. They get parameters such as "a", "b" and "c" (example below). But how come that we can "link" the function to an object f that itself can contain 0 as parameters that will then be computed by our lambda expression?

def build_quadratic_function(a,b,c):
     return lambda x: a*x**2 + b*x+c

f = build_quadratic_function(2,3,-5)

f(0)

yields:

-5

In layman words, how does the function "know" that 0 must be read by the lambda expression that is contained in the function? Can somebody explain the mechanism behind it?

Thank you!

Upvotes: 3

Views: 84

Answers (4)

tdelaney
tdelaney

Reputation: 77357

This isn't a lambda specific thing. Its a "closure" and can be done with a regular function also. In fact, a lambda is just an anonymous function. Its it restricted to implementing an expression instead of full python statements, but that's only the case because of python parsing issues. So, this is the same thing

def build_quadratic_function(a,b,c):
    def inner(x):
        return a*x**2 + b*x+c
    return inner

inner uses variables from the enclosing function. When build_quadratic_function returns inner, the current objects in a, b and c are bound to inner. Later, when inner(someval) is called, those bound objects to a, b and c are used. x, which is a parameter to inner needs to be supplied on each call.

You can get the inner function once and use it many times with the same values.

func = build_quadratic_function(1,2,3)
for i in range(10):
    print(func(i))

Upvotes: 1

Celius Stingher
Celius Stingher

Reputation: 18367

A very similar example can be found in the documentation.

Lambdas are small anonymous functions. They can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition. Like nested function definitions, lambda functions can reference variables from the containing scope.

Therefore if you define a custom function that contains a lambda, and then fix its parameters, it's essentially the same as defining a lambda function and then passing the expression.

For the sake of your example:

def build_quadratic_function(a,b,c):
     return lambda x: a*x**2 + b*x+c

f = build_quadratic_function(2,3,-5)

Would create the same output as:

f = lambda x: 2*x**2 + 3*x - 5

In either case, when you call f(0) then the expression gets evaluated with value 0 returning -5.

2*0**2 + 3*0 - 5 = - 5

The improvement using a custom function over the simple definition of the lambda itself is you can modify the a, b and c parameters.

Upvotes: 1

Ahmed
Ahmed

Reputation: 74

A lambda function is a small anonymous function. (function with no name)

f = build_quadratic_function(2,3,-5)

Till this point, f is equal to the return value of build_quadratic_function, which is another function(lambda in this case)!

f(0) calls the lambda which is waiting

Upvotes: 0

timgeb
timgeb

Reputation: 78740

def build_quadratic_function(a,b,c):
     return lambda x: a*x**2 + b*x + c

is (in all important aspects) equivalent to

def build_quadratic_function(a,b,c):
    def func(x):
        return a*x**2 + b*x + c      
    return func

In both cases, the inner function, be it an anonymous one or not, is holding onto the variables in the enclosing scope. You have discovered so called closures.

>>> import inspect
>>> f = build_quadratic_function(2, 3, -5)
>>> inspect.getclosurevars(f)
ClosureVars(nonlocals={'a': 2, 'b': 3, 'c': -5}, globals={}, builtins={}, unbound=set())

Upvotes: 2

Related Questions