Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading (or alternatives) in Python API design

I have a large existing program library that currently has a .NET binding, and I'm thinking about writing a Python binding. The existing API makes extensive use of signature-based overloading. So, I have a large collection of static functions like:

Circle(p1, p2, p3) -- Creates a circle through three points
Circle(p, r)       -- Creates a circle with given center point and radius
Circle(c1, c2, c3) -- Creates a circle tangent to three curves

There are a few cases where the same inputs must be used in different ways, so signature-based overloading doesn't work, and I have to use different function names, instead. For example

BezierCurve(p1,p2,p3,p4) -- Bezier curve using given points as control points
BezierCurveThroughPoints(p1,p2,p3,p4) -- Bezier curve passing through given points

I suppose this second technique (using different function names) could be used everywhere in the Python API. So, I would have

CircleThroughThreePoints(p1, p2, p3)
CircleCenterRadius(p, r)
CircleTangentThreeCurves(c1, c2, c3)

But the names look unpleasantly verbose (I don't like abbreviations), and inventing all of them will be quite a challenge, because the library has thousands of functions.

Low Priorities:
Effort (on my part) -- I don't care if I have to write a lot of code.
Performance

High Priorities:
Ease of use/understanding for callers (many will be programming newbies).
Easy for me to write good documentation.
Simplicity -- avoid the need for advanced concepts in caller's code.

I'm sure I'm not the first person who ever wished for signature-based overloading in Python. What work-arounds do people typically use?

like image 545
bubba Avatar asked Aug 16 '14 02:08

bubba


People also ask

Why overloading is not supported in Python?

Why no Function Overloading in Python? Python does not support function overloading. When we define multiple functions with the same name, the later one always overrides the prior and thus, in the namespace, there will always be a single entry against each function name.

Does Python support overloading methods?

Python supports both function and operator overloading. In function overloading, we can use the same name for many Python functions but with the different number or types of parameters.

What is overloading method in Python?

Two methods cannot have the same name in Python; hence method overloading is a feature that allows the same operator to have different meanings. Overloading is a method or operator that can do different functionalities with the same name.

Does Python support function overloading and overriding?

Note: Python does not support method overloading. We may overload the methods but can only use the latest defined method.


Video Answer


1 Answers

One option is to exclusively keyword arguments in the constructor, and include logic to figure out what should be used:

class Circle(object):
    def __init__(self, points=(), radius=None, curves=()):
        if radius and len(points) == 1:
            center_point = points[0]
            # Create from radius/center point
        elif curves and len(curves) == 3:
            # create from curves
        elif points and len(points) == 3:
            # create from points
        else:
            raise ValueError("Must provide a tuple of three points, a point and a radius, or a tuple of three curves)

You can also use classmethods to make things easier for the users of the API:

class Circle(object):
    def __init__(self, points=(), radius=None, curves=()):
         # same as above

    @classmethod
    def from_points(p1, p2, p3):
        return cls(points=(p1, p2, p3))

    @classmethod
    def from_point_and_radius(cls, point, radius):
        return cls(points=(point,), radius=radius)

    @classmethod
    def from_curves(cls, c1, c2, c3):
        return cls(curves=(c1, c2, c3))

Usage:

c = Circle.from_points(p1, p2, p3)
c = Circle.from_point_and_radius(p1, r)
c = Circle.from_curves(c1, c2, c3)
like image 104
dano Avatar answered Sep 29 '22 15:09

dano