Python has a cool feature that allows you to overload the operators. Let’s talk about what that means and how you might use it!
Table of Contents
- Concept Overview
- How Do You Overload an Operator?
- Isn’t Operator Overloading Bad Practice?
- Overloading Your Brain
Concept Overview
As a concept in computer science, overloading typically refers to the ability to have multiple behaviors for the same syntax. For example, you may be familiar with method overloading, which is when multiple methods have the same name but different sets of parameters.
Extending the concept of overloading to operators introduces the ability to have multiple behaviors for the same operator. Not all programming languages support operator overloading, but Python is one of them. That’s why you will sometimes see familiar operators used in strange contexts.
To illustrate this point, consider the addition operator (i.e., +
). The addition operator can be used to add numbers together:
5 + 7 # evaluates to 12
Of course, the addition operator can also be used to concatenate strings:
"Yusuke" + "Urameshi" # evaluates to "YusukeUrameshi"
Or, you might use the addition operator to combine lists:
[1, 2] + [3, 4] # evaluates to [1, 2, 3, 4]
In fact, there are probably a dozen native uses for the addition operator. That’s the power of operator overloading! In the remainder of this article, we’ll look at some questions you might have about operator overloading.
How Do You Overload an Operator?
Operators are defined at the class level. In other words, you can overload an operator for any custom type you would like. As a simple example, we might imagine making a 2D point class as follows:
class Point2D: def __init__(self, x: int, y: int): self.x = x self.y = y
And just so we can see how it works, we should also implement the repr()
method:
class Point2D: def __init__(self, x: int, y: int): self.x = x self.y = y def __repr__(self): return f"({self.x}, {self.y})"
Now, when we create a point in a REPL like IDLE, we can see the point in typical notation:
>>> Point2D(3, 4) (3, 4)
Next, we can overload the addition operator by implementing the add()
method:
class Point2D: def __init__(self, x: int, y: int): self.x = x self.y = y def __repr__(self): return f"({self.x}, {self.y})" def __add__(self, other): return Point2D(self.x + other.x, self.y + other.y)
Now, when two points are added together, we will get a new point with their components summed together:
>>> Point2D(3, 4) + Point2D(1, 2) (4, 6)
Note that I don’t think it’s proper math to be able to add two points together. That’s more of a vector thing, but you get the idea!
Isn’t Operator Overloading Bad Practice?
You may have heard that operator overloading is bad practice. After all, some programming languages like Java prohibit it. In my experience, it’s a delicate balance. It is definitely possible to overload operators in a way that makes code harder to read (e.g., overloading obscure operators). It’s also possible to overload operators in a way that purposely confuses the reader (e.g., overloading subtraction to do addition).
With that said, in programming languages like Java where operator overloading is not possible, you can really feel it. For example, you might have used the Comparator interface at some point in Java. It’s practically required to know how to use a Comparator in Java because so much of the standard library relies on it for sorting and ordering elements. As a result, you’ve certainly come across the following syntax:
if (x.compareTo(y) > 0) { ... }
No matter how many times I see this syntax, I have to remind myself what it means. If Java simply allowed us to overload the less-than and greater-than operators, we could have syntax like the following:
if (x > y) { ... }
Fortunately, I am not the only one irritated by this limitation. In fact, the developers of Kotlin have as well, and any attempts to use the typical Comparator syntax will result in some linter warnings.
With that said, I do think there’s an issue with languages that have too many operators (e.g., Perl). Explicit is generally going to be better than implicit, so flooding a language with symbols is not ideal. That’s partially why folks got so fired up about the walrus operator back in Python 3.8.
Overloading Your Brain
Personally, operator overloading is not a feature I use very often. However, in the few case I have, it’s made my code a lot easier to use. I would recommend at least toying with the feature because it’s not just available for the math or relational operators. You can also overload the indexing syntax (i.e., x[i]
).
At any rate, let’s call it a day! Hopefully you enjoyed this one. If not, why not try one of the following articles:
- Abusing Python’s Operator Overloading Feature
- Explain Like I’m Five: Method Overloading
- Java Has A Remainder Operator—Not a Mod Operator
Likewise, you might enjoy some of these resources (#ad):
- Effective Python: 90 Specific Ways to Write Better Python
- Python Tricks: A Buffet of Awesome Python Features
- Python Programming: An Introduction to Computer Science
Alternatively, you might enjoy taking your support a step further by checking out my list of ways to grow the site. If not, no sweat! Take care.
Recent Code Posts
One of the core features of modern programming languages is functions, but did you know Python has them too? Let's take a look!
This week, we're hitting another beginner topic: the assignment operator. While the idea is simple, the concept is rich in related ideas like scope, iterable unpacking, and augmented assignment.