Reputation: 11
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
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
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
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
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
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