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?
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.
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.
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.
Note: Python does not support method overloading. We may overload the methods but can only use the latest defined method.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With