2

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.

4
  • 2
    What book are you using? Is it intended to be used with Python? It might just be a bad book.
    – Daenyth
    CommentedDec 7, 2015 at 17:34
  • You can fake function overloading pretty easily with a **kw argument, though it is not clear that's what is being asked by the book. True function overloading does not exist in Python.
    – user53141
    CommentedDec 7, 2015 at 21:28
  • My book is a standard book issued by the govt of india(cbse)...and by the way this question is in many of the other indian books...but as shenshin said even i think its been copied from some c++ book as python is just introduced to curriculum... And c++ supports function overloading so the code is easy there.....
    – geek101
    CommentedDec 8, 2015 at 19:40
  • I tried doing this problem with an abstract method....it worked ! That could be an alternative solution.
    – geek101
    CommentedDec 8, 2015 at 19:46

3 Answers 3

6

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.

    2

    Python does not support function overloading, however, it does give you the tools to implement it yourself in a fairly straightforward manner.

    Using **kw in the parameter list will pass all arguments in a dictionary. In order to simulate function overloading, you test for the existence of parameters yourself and dispatch appropriately:

    def foo_x_y(x, y): print("x is %d y is %d" % (x,y)) def foo_h_l(h, l): print("h is %d l is %d" % (h,l)) def foo(**kw): if 'x' in kw and 'y' in kw: return foo_x_y(kw['x'], kw['y']) elif 'h' in kw and 'l' in kw: return foo_h_l(kw['h'], kw['l']) raise TypeError("foo() takes exactly 2 argument (%d given)" % len(kw)) >> foo(x=1, y=2) x is 1 y is 2 >> foo(h=2, l=1) h is 2 l is 1 >> foo(z=1) File "foo.py", line 18, in <module> foo(z=1) File "foo.py", line 13, in foo raise TypeError("foo() takes exactly 2 argument (%d given)" % len(kw)) TypeError: foo() takes exactly 2 argument (1 given) 

    This takes more legwork, but is more flexible than overloading. It makes it easier to "overload" in ways that involve a single core implementation, for example:

    def arc_length(**kw): if 'diameter' not in kw: raise TypeError if 'radians' not in kw or 'degrees' not in kw: raise TypeError if 'radians' in kw and 'degrees' in kw: raise TypeError diameter = kw['diameter'] if degrees in kw: radians = degrees_to_radians(kw['degrees']) else: radians = kw['radians'] # calculate arc length using radians and diameter arc_length(diameter=10, degrees=30) arc_length(diameter=10, radians=1.2) 
      1

      It's possible the book is using incorrect wording and is actually asking you to use OO inheritance.

      class Shape(object): def volume(): raise NotImplementedError() class Cube(Shape): def __init__(self, side_length): self.side = side_length def volume(): return self.side * self.side * self.side class Cylinder(Shape): def volume(): ... 

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.