Fintan Healy
Fintan Healy

Reputation: 11

How to write a function that returns a function in Python?

In one of the training parts of my course I was given the following question:

Write a function make_multiplier(factor) that returns a function which takes an argument x and which should return factor * x.

For example:

f=make_multiplier(10)
f(1)
10
f(2)
20

I have absolutely no idea where to start with this one; I have scrummaged through all my notes and cant find anything useful.

Could someone please give me a hint or point me in the right direction of what I need to do?

Upvotes: 1

Views: 728

Answers (5)

pillmuncher
pillmuncher

Reputation: 10162

I'm not recommending this, I'm just showing what's possible in point-lessfree style:

>>> from functools import partial
>>> from operator import mul
>>> make_multiplier = partial(partial, mul)
>>> f = make_multiplier(10)
>>> f(1)
10
>>> f(2)
20

Upvotes: 0

Jeremy
Jeremy

Reputation: 393

Using lambdas:

>>> make_multiplier = lambda n: lambda x: x * n
>>> make_multiplier(10)(5)
50

10000000 loops, best of 3: 0.189 usec per loop

Using stdlib:

import functools
import operator

f = lambda n: functools.partial(operator.mul, n)

10000000 loops, best of 3: 0.148 usec per loop

Upvotes: 0

the wolf
the wolf

Reputation: 35572

In addition to Matt Ball or Martijn Pieters closure methods (which is the right answer in this particular case) there are two other forms that you will see that are worth recognizing in Python.

The first is using a lambda anonymous function:

>>> f=lambda x: x*10
>>> f(1)
10
>>> f(2)
20

The second is writing a class:

class Multiplyby:
    def __init__(self,x):
        self.x=x

    def __call__(self,y):
        return self.x*y

fx10=Multiplyby(10)
fx5=Multiplyby(5)


for y in [1,2,3]:
    print y, fx10(y), fx5(y)

prints:

1 10 5
2 20 10
3 30 15

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1125058

Dead simple, just nest your functions:

def make_multiplier(x):
    def multiplier(y):
        return x * y
    return multiplier

Nested functions automatically look up unknown variables (x in this case) from their surrounding scope, using the value of x as it was when the outer function was called. The thing to remember here is that functions are just objects too, you can store them in a variable just like you can with other python objects, and defer calling them.

This gives:

>>> def make_multiplier(x):
...     def multiplier(y):
...         return x * y
...     return multiplier
... 
>>> f = make_multiplier(10)
>>> f(1)
10
>>> f(2)
20
>>> g = make_multiplier(5)
>>> g(1)
5
>>> f(3)
30

Note how g was given a different value for x, which is independent from the value for x in f.

You could use a lambda as well; lambdas are just anonymous functions limited to one expression; that's enough here:

def make_multiplier(x):
    return lambda y: x * y

Another alternative technique is binding x to a keyword parameter, which means you could override it if you so wish:

def make_multiplier(x):
    def multiply(y, x=x):
         return x * y
    return multiply

or the lambda version:

def make_multiplier(x):
    return lambda y, x=x: x * y

and then pass in one or two arguments to the returned callable:

>>> f = make_multiplier(10)
>>> f(5)
50
>>> f(5, 3)
15

Upvotes: 3

Matt Ball
Matt Ball

Reputation: 360046

Here is a function that returns a function:

def foo():
    def bar():
        return 42

    return bar

You can call it like so:

foo()() # 42
# or
baz = foo()
baz() # 42

There's your hint.

Upvotes: 4

Related Questions