Function Overloading Techniques in Python

functional programmingobject-orientedpython

My book says that function overloading is not possible in python but it asks me questions like:

WAP to find out the volume of a cube,cuboid and cylinder using function overloading.

Do I have to involve decorators here?

How am I supposed to involve functional overloading in my program?

I saw a similar question where wraps from functools was used but failed to understand it.

If functional overloading is not involved then it is child's play…

P.S-I am in grade 12 and we haven't been taught much about decorators.

Best Answer

If you're using Python 3.4 or newer, you have access to functools.singledispatch (thanks to PEP 443), which lets you overload functions (preferably unary) much like you would in a language like Java.

If you define your various polyhedra as classes, you can dispatch on their types, like so:

import math
from functools import singledispatch


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

class Cuboid:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

class Cylinder:
    def __init__(self, *, r, h):
        self.r = r
        self.h = h

# Mark this function as single-dispatchable.
@singledispatch
def volume(polyhedron):
    pass # Or throw an exception, or something like that.

def _volume_cube(cube):
    return cube.x ** 3

def _volume_cuboid(cuboid):
    return cuboid.x * cuboid.y * cuboid.z

def _volume_cylinder(cylinder):
    return math.pi * (cylinder.r) ** 2 * cylinder.h

# Register handlers for the types for which you can compute volumes.
volume.register(Cube, _volume_cube)
volume.register(Cuboid, _volume_cuboid)
volume.register(Cylinder, _volume_cylinder)

Now, you can do this:

>>> cube = Cube(4)
>>> volume(cube)
64
>>> cuboid = Cuboid(3, 5, 7)
>>> volume(cuboid)
105
>>> cylinder = Cylinder(r=2, h=4)
>>> volume(cylinder)
50.26548245743669

If you're using a version older than 3.4, you don't really have any good options for this sort of transparent single dispatch (though you could always just backport functools.singledispatch if you're on an earlier 3.x - it's written in pure Python and I don't think it relies on any new 3.4 features). You could, instead, have a function volume(cube=None, cuboid=None, cylinder=None), or volume(polyhedron) and dispatch on type(polyhedron) inside the function, or do some magic with **kwargs.

All that said, I somehow doubt that your book wants you to use functools.singledispatch - I'd hazard a guess that somebody just copied the problems out of a C++ or Java book without really thinking about it.

Related Topic