How do I write a function that returns another function?

PythonFunctionFunctional ProgrammingCurrying

Python Problem Overview


In Python, I'd like to write a function make_cylinder_volume(r) which returns another function. That returned function should be callable with a parameter h, and return the volume of a cylinder with height h and radius r.

I know how to return values from functions in Python, but how do I return another function?

Python Solutions


Solution 1 - Python

Try this, using Python:

import math
def make_cylinder_volume_func(r):
	def volume(h):
		return math.pi * r * r * h
	return volume

Use it like this, for example with radius=10 and height=5:

volume_radius_10 = make_cylinder_volume_func(10)
volume_radius_10(5)
=> 1570.7963267948967

Notice that returning a function was a simple matter of defining a new function inside the function, and returning it at the end - being careful to pass the appropriate parameters for each function. FYI, the technique of returning a function from another function is known as currying.

Solution 2 - Python

Using lambdas, also known as anonymous functions, you can abstract out the volume function inside the make_cylinder_volume_func to a single line. In no way different from Óscar López's answer, the solution using lambda is still in a sense 'more functional'.

This is how you can write the accepted answer using a lambda expression:

import math
def make_cylinder_volume_fun(r):
    return lambda h: math.pi * r * r * h

And then call as you'd any other curried function:

volume_radius_1 = make_cylinder_volume_fun(1)
volume_radius_1(1) 
=> 3.141592653589793

Solution 3 - Python

Just want to point out that you can do this with pymonad

 import pymonad 
 
 @pymonad.curry
 def add(a, b):
     return a + b
 
 add5 = add(5)
 add5(4)
 9

Solution 4 - Python

I know I am too late to the party, but I think you might find this solution interesting.

from math import pi
from functools import partial

def cylinder_volume(r, h):
	return pi * r * r * h

make_cylinder_with_radius_2 = partial(cylinder_volume, 2)
make_cylinder_with_height_3 = partial(cylinder_volume, h=3)

print(cylinder_volume(2, 3)) 			# 37.6991118431
print(make_cylinder_with_radius_2(3))	# 37.6991118431
print(make_cylinder_with_height_3(2))	# 37.6991118431

Here is documentation about how partial works.

Solution 5 - Python

Here is one massive example which covers many of single multiple argument cases in one function

def maths(var='NA'):
if var.lower() == 'add':
    def add(*args):
        return "Sum is : "+str(sum(args))
    return add
elif var.lower() == 'substract':
    def substract(a,b):
        if a>b:
            return "Difference is : "+str(a-b)
        else:
            return "Difference is : "+str(b-a)
    return substract
elif var.lower() == 'multiply':
    def multiply(*args):
        temp = 1
        for x in args:
            temp = temp*x
        return "multiplication is : "+str(temp)
    return multiply
elif var.lower() == 'divide':
    def divide(a,b):
        return "Division is : "+str(a/b)
    return divide
else:
    print("Please choose one of given operations: 'add','substract','multiply','divide'")

Here first call the maths function with the required operation and then use the returned function for the actual calculation

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJulian DasView Question on Stackoverflow
Solution 1 - PythonÓscar LópezView Answer on Stackoverflow
Solution 2 - PythonDaveIditoView Answer on Stackoverflow
Solution 3 - PythonErotemicView Answer on Stackoverflow
Solution 4 - PythonR3ctorView Answer on Stackoverflow
Solution 5 - PythonRahul VaidyaView Answer on Stackoverflow