Function overloading is critical to polymorphism, wherein, we may have multiple functions with:
Same name, and
Different number (or type) of parameters.
However, Python provides no native support for function overloading.
In other words, if we define two (or more) functions with the same name and different parameters, Python will only consider the latest definition corresponding to that function name.
This is depicted below.
As depicted above, the latest definition of add()
had three parameters. That is why passing two arguments raised an error.
This restricts us from writing good polymorphic code in Python.
Of course, there are ways to prevent this error, as depicted below:
Also, if the same parameter can take multiple data types, we can write (somewhat) polymorphic code by adding multiple check statements using isinstance()
.
But this isn’t as elegant as defining multiple functions with different data types like we can do in, say, C++, is it?
C++ automatically invokes the correct method corresponding to the argument data type.
Lately, while exploring this for one of my projects, I found a pretty handy way to enable function overloading in Python and thought it’d be quite useful for many of you.
The @dispatch
decorator from the Multidispatch library allows us to leverage the standard and elegant function overloading in Python, as demonstrated below:
As depicted above, we have multiple functions with the same name and different parameters.
The @dispatch
decorator allows us to invoke the correct function corresponding to the parameters passed during the function call.
Another cool thing about the @dispatch
decorator is that it raises an error when the function call does not match any of the function definitions:
This allows us to identify errors which can often go unnoticed.
Isn’t that cool?
In a dummy experimentation, I did notice a slight increment in the run time. But the order of increase was in nanoseconds or so, which can be safely ignored.
That said, if you want to get really good at Python OOP, learn about Python Descriptors.
I find them to be massively helpful in reducing work and code redundancy while also making the entire implementation much more elegant.
We covered it in this newsletter here: Define Elegant and Concise Python Classes with Descriptors.
👉 Over to you: What other cool Python libraries you are aware of?
Thanks for reading!
Are you preparing for ML/DS interviews or want to upskill at your current job?
Every week, I publish in-depth ML dives. The topics align with the practical skills that typical ML/DS roles demand.
Join below to unlock all full articles:
Here are some of the top articles:
[FREE] A Beginner-friendly and Comprehensive Deep Dive on Vector Databases.
5 Must-Know Ways to Test ML Models in Production (Implementation Included)
A Detailed and Beginner-Friendly Introduction to PyTorch Lightning: The Supercharged PyTorch
Don’t Stop at Pandas and Sklearn! Get Started with Spark DataFrames and Big Data ML using PySpark.
Federated Learning: A Critical Step Towards Privacy-Preserving Machine Learning.
You Cannot Build Large Data Projects Until You Learn Data Version Control!
Sklearn Models are Not Deployment Friendly! Supercharge Them With Tensor Computations.
You Are Probably Building Inconsistent Classification Models Without Even Realizing
Join below to unlock all full articles:
👉 If you love reading this newsletter, share it with friends!
👉 Tell the world what makes this newsletter special for you by leaving a review here :)
That's actually a very pratical low-level concept. Thanks a lot!
Aren't there other more pythonic ways such as duck typing or protocols to approach these problems, rather than doing something "like it's done in C++"?